diff --git a/smocore/senseApis/senseApiManager.cpp b/smocore/senseApis/senseApiManager.cpp index e0fab75..e30851e 100644 --- a/smocore/senseApis/senseApiManager.cpp +++ b/smocore/senseApis/senseApiManager.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include @@ -313,136 +315,118 @@ void SenseApiManager::detachSenseDeviceReq( void SenseApiManager::attachAllSenseDevicesFromSpecs(void) { - std::atomic nTotal = device::DeviceManager::deviceAttachmentSpecs - .size(); - std::atomic nSucceeded = 0, nFailed = 0; - auto self = ComponentThread::getSelf(); + AsynchronousBridge bridge(self->getIoService()); + AsynchronousLoop loop(device::DeviceManager::deviceAttachmentSpecs.size()); + for (const auto& spec : device::DeviceManager::deviceAttachmentSpecs) { try { attachSenseDeviceReq(spec, - [spec, &nTotal, &nSucceeded, &nFailed, caller = self](bool success) -> void + [spec, &loop, &bridge](bool success) -> void { if (!success) { - ++nFailed; + ++loop.nFailed; std::cerr << __func__ << ": Failed to attach device: " << spec->deviceIdentifier << "\n"; - caller->getIoService().post([]{}); return; } - ++nSucceeded; - if (nSucceeded.load() + nFailed.load() != nTotal.load()) { - return; - } + ++loop.nSucceeded; + if (!loop.isComplete()) { return; } - std::cout << __func__ << ": " << nSucceeded.load() + std::cout << __func__ << ": " << loop.nSucceeded.load() << " devices attached, " - << nFailed.load() << " devices failed\n"; - caller->getIoService().post([]{}); + << loop.nFailed.load() << " devices failed\n"; + + bridge.setAsyncOperationComplete(); }); } catch (const std::exception& e) { std::cerr << __func__ << ": Exception: " << e.what() << "\n"; - ++nFailed; + ++loop.nFailed; + if (loop.isComplete()) + { bridge.setAsyncOperationComplete(); } } } /* Bridge the async op here. */ - for (;;) - { - self->getIoService().run_one(); - if ((nSucceeded.load() + nFailed.load() == nTotal.load()) - || self->getIoService().stopped()) - { - break; - } - } - - if (self->getIoService().stopped()) + bridge.waitForAsyncOperationCompleteOrIoServiceStopped(); + if (bridge.exitedBecauseIoServiceStopped()) { /* Return early because the io_service is stopped. */ return; } - if (nTotal.load() != nSucceeded.load() + nFailed.load()) + if (loop.nTotal.load() != loop.nSucceeded.load() + loop.nFailed.load()) { throw std::runtime_error( std::string(__func__) + ": Failed to get through all devices"); } - std::cout << __func__ << ": " << nSucceeded.load() << "/" << nTotal.load() - << " devices attached, " - << nFailed.load() << "/" << nTotal.load() << " devices failed\n"; + std::cout << __func__ << ": " << loop.nSucceeded.load() << "/" + << loop.nTotal.load() << " devices attached, " + << loop.nFailed.load() << "/" << loop.nTotal.load() + << " devices failed\n"; } void SenseApiManager::detachAllSenseDevicesReq(void) { - std::atomic nTotal = device::DeviceManager::deviceAttachmentSpecs - .size(); - std::atomic nSucceeded = 0, nFailed = 0; - auto self = ComponentThread::getSelf(); + AsynchronousBridge bridge(self->getIoService()); + AsynchronousLoop loop(device::DeviceManager::deviceAttachmentSpecs.size()); + for (const auto& spec : device::DeviceManager::deviceAttachmentSpecs) { try { detachSenseDeviceReq(spec, - [spec, &nTotal, &nSucceeded, &nFailed, caller = self](bool success) -> void + [spec, &loop, &bridge](bool success) -> void { if (!success) { - ++nFailed; + ++loop.nFailed; std::cerr << __func__ << ": Failed to detach device: " << spec->deviceIdentifier << "\n"; - caller->getIoService().post([]{}); return; } - ++nSucceeded; - if (nSucceeded.load() + nFailed.load() != nTotal.load()) { - return; - } + ++loop.nSucceeded; + if (!loop.isComplete()) { return; } - std::cout << __func__ << ": " << nSucceeded.load() + std::cout << __func__ << ": " << loop.nSucceeded.load() << " devices detached, " - << nFailed.load() << " devices failed\n"; - caller->getIoService().post([]{}); + << loop.nFailed.load() << " devices failed\n"; + + bridge.setAsyncOperationComplete(); }); } catch (const std::exception& e) { std::cerr << __func__ << ": Exception: " << e.what() << "\n"; - ++nFailed; + ++loop.nFailed; + if (loop.isComplete()) + { bridge.setAsyncOperationComplete(); } } } /* Bridge the async op here. */ - for (;;) - { - self->getIoService().run_one(); - if ((nSucceeded.load() + nFailed.load() == nTotal.load()) - || self->getIoService().stopped()) - { - break; - } - } - - if (self->getIoService().stopped()) + bridge.waitForAsyncOperationCompleteOrIoServiceStopped(); + if (bridge.exitedBecauseIoServiceStopped()) { /* Return early because the io_service is stopped. */ return; } - if (nTotal.load() != nSucceeded.load() + nFailed.load()) + if (loop.nTotal.load() != loop.nSucceeded.load() + loop.nFailed.load()) { throw std::runtime_error( std::string(__func__) + ": Failed to get through all devices"); } - std::cout << __func__ << ": " << nSucceeded.load() << "/" << nTotal.load() - << " devices detached, " - << nFailed.load() << "/" << nTotal.load() << " devices failed\n"; + std::cout << __func__ << ": " << loop.nSucceeded.load() << "/" + << loop.nTotal.load() << " devices detached, " + << loop.nFailed.load() << "/" << loop.nTotal.load() + << " devices failed\n"; } } // namespace sense_api