SenseApis: Make attachDeviceReq async in drivers and SenseApiMgr
Slowly retrogressively making these sequences async
This commit is contained in:
@@ -54,6 +54,7 @@ const std::string DeviceManager::stringifyDeviceSpecs(void)
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
#if 0
|
||||
void DeviceManager::newDeviceAttachmentSpecInd(
|
||||
std::shared_ptr<DeviceAttachmentSpec> spec,
|
||||
std::function<void(
|
||||
@@ -109,6 +110,7 @@ void DeviceManager::newDeviceAttachmentSpecInd(
|
||||
callback(false, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace device
|
||||
} // namespace smo
|
||||
|
||||
@@ -30,13 +30,13 @@ public:
|
||||
static const std::string stringifyDeviceSpecs(void);
|
||||
|
||||
// New async function for device attachment
|
||||
void newDeviceAttachmentSpecInd(
|
||||
typedef std::function<void(
|
||||
bool success, std::shared_ptr<Device> device,
|
||||
std::shared_ptr<DeviceAttachmentSpec> deviceSpec)>
|
||||
deviceAttachmentSpecIndCbFn;
|
||||
void newDeviceAttachmentSpecInd(
|
||||
std::shared_ptr<DeviceAttachmentSpec> spec,
|
||||
std::function<
|
||||
void(
|
||||
bool success, std::shared_ptr<Device> device,
|
||||
std::shared_ptr<DeviceAttachmentSpec> deviceSpec)>
|
||||
callback);
|
||||
deviceAttachmentSpecIndCbFn callback);
|
||||
|
||||
private:
|
||||
DeviceManager() = default;
|
||||
|
||||
@@ -43,12 +43,18 @@ public:
|
||||
void initializeAllSenseApiLibs(void);
|
||||
void finalizeAllSenseApiLibs(void);
|
||||
|
||||
void attachAllSenseDevicesFromSpecs(void);
|
||||
void attachSenseDevice(
|
||||
const std::shared_ptr<device::DeviceAttachmentSpec>& spec);
|
||||
void detachSenseDevice(
|
||||
const std::shared_ptr<device::DeviceAttachmentSpec>& spec);
|
||||
void detachAllSenseDevices(void);
|
||||
typedef sal_mlo_attachDeviceReqCbFn attachSenseDeviceReqCbFn;
|
||||
typedef sal_mlo_detachDeviceReqCbFn detachSenseDeviceReqCbFn;
|
||||
|
||||
void attachSenseDeviceReq(
|
||||
const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
|
||||
attachSenseDeviceReqCbFn cb);
|
||||
void detachSenseDeviceReq(
|
||||
const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
|
||||
detachSenseDeviceReqCbFn cb);
|
||||
void attachAllSenseDevicesFromSpecs(void);
|
||||
void detachAllSenseDevices(void);
|
||||
void detachAllSenseDevicesReq(void);
|
||||
|
||||
std::string stringifyLibs() const;
|
||||
|
||||
@@ -61,6 +67,9 @@ private:
|
||||
|
||||
std::vector<std::shared_ptr<SenseApiLib>> senseApiLibs;
|
||||
|
||||
class AttachSenseDeviceReq;
|
||||
class DetachSenseDeviceReq;
|
||||
|
||||
public:
|
||||
static std::optional<std::string> searchForLibInSmoSearchPaths(
|
||||
const std::string& libraryPath);
|
||||
|
||||
@@ -28,7 +28,7 @@ void shutdownSalmanoff(void)
|
||||
{
|
||||
std::cout << __func__ << ": Entered." << std::endl;
|
||||
|
||||
sense_api::SenseApiManager::getInstance().detachAllSenseDevices();
|
||||
sense_api::SenseApiManager::getInstance().detachAllSenseDevicesReq();
|
||||
sense_api::SenseApiManager::getInstance().finalizeAllSenseApiLibs();
|
||||
|
||||
std::cout << __func__ << ": Done." << std::endl;
|
||||
|
||||
@@ -255,11 +255,19 @@ void SenseApiManager::finalizeAllSenseApiLibs(void)
|
||||
}
|
||||
}
|
||||
|
||||
void SenseApiManager::attachSenseDevice(
|
||||
const std::shared_ptr<device::DeviceAttachmentSpec>& spec
|
||||
|
||||
|
||||
void SenseApiManager::attachSenseDeviceReq(
|
||||
const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
|
||||
attachSenseDeviceReqCbFn cb
|
||||
)
|
||||
{
|
||||
auto libOpt = getSenseApiLibByApiName(spec->api);
|
||||
/** FIXME:
|
||||
* We should acquire a spinlock here to ensure that the device isn't added
|
||||
* in the interim while the async op executes.
|
||||
*/
|
||||
|
||||
auto libOpt = getSenseApiLibByApiName(spec->api);
|
||||
if (!libOpt)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
@@ -273,13 +281,19 @@ void SenseApiManager::attachSenseDevice(
|
||||
std::string(__func__) + ": attachDeviceReq() is NULL for library '"
|
||||
+ lib.libraryPath + "'");
|
||||
}
|
||||
lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq(spec);
|
||||
lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq(spec, cb);
|
||||
}
|
||||
|
||||
void SenseApiManager::detachSenseDevice(
|
||||
const std::shared_ptr<device::DeviceAttachmentSpec>& spec
|
||||
void SenseApiManager::detachSenseDeviceReq(
|
||||
const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
|
||||
detachSenseDeviceReqCbFn cb
|
||||
)
|
||||
{
|
||||
/** FIXME:
|
||||
* We should acquire a spinlock here to ensure that the device isn't removed
|
||||
* in the interim while the async op executes.
|
||||
*/
|
||||
|
||||
auto libOpt = getSenseApiLibByApiName(spec->api);
|
||||
if (!libOpt)
|
||||
{
|
||||
@@ -294,21 +308,141 @@ void SenseApiManager::detachSenseDevice(
|
||||
std::string(__func__) + ": detachDeviceReq() is NULL for library '"
|
||||
+ lib.libraryPath + "'");
|
||||
}
|
||||
lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq(spec);
|
||||
lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq(spec, cb);
|
||||
}
|
||||
|
||||
void SenseApiManager::attachAllSenseDevicesFromSpecs(void)
|
||||
{
|
||||
for (const auto& spec : device::DeviceManager::deviceAttachmentSpecs) {
|
||||
attachSenseDevice(spec);
|
||||
}
|
||||
std::atomic<int> nTotal = device::DeviceManager::deviceAttachmentSpecs
|
||||
.size();
|
||||
std::atomic<int> nSucceeded = 0, nFailed = 0;
|
||||
|
||||
auto self = ComponentThread::getSelf();
|
||||
for (const auto& spec : device::DeviceManager::deviceAttachmentSpecs)
|
||||
{
|
||||
try {
|
||||
attachSenseDeviceReq(spec,
|
||||
[spec, &nTotal, &nSucceeded, &nFailed, caller = self](bool success) -> void
|
||||
{
|
||||
if (!success)
|
||||
{
|
||||
++nFailed;
|
||||
std::cerr << __func__ << ": Failed to attach device: "
|
||||
<< spec->deviceIdentifier << "\n";
|
||||
|
||||
caller->getIoService().post([]{});
|
||||
return;
|
||||
}
|
||||
|
||||
++nSucceeded;
|
||||
if (nSucceeded.load() + nFailed.load() != nTotal.load()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << __func__ << ": " << nSucceeded.load()
|
||||
<< " devices attached, "
|
||||
<< nFailed.load() << " devices failed\n";
|
||||
caller->getIoService().post([]{});
|
||||
});
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << __func__ << ": Exception: " << e.what() << "\n";
|
||||
++nFailed;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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())
|
||||
{
|
||||
/* Return early because the io_service is stopped. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (nTotal.load() != nSucceeded.load() + 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";
|
||||
}
|
||||
|
||||
void SenseApiManager::detachAllSenseDevices(void)
|
||||
void SenseApiManager::detachAllSenseDevicesReq(void)
|
||||
{
|
||||
for (const auto& spec : device::DeviceManager::deviceAttachmentSpecs) {
|
||||
detachSenseDevice(spec);
|
||||
}
|
||||
std::atomic<int> nTotal = device::DeviceManager::deviceAttachmentSpecs
|
||||
.size();
|
||||
std::atomic<int> nSucceeded = 0, nFailed = 0;
|
||||
|
||||
auto self = ComponentThread::getSelf();
|
||||
for (const auto& spec : device::DeviceManager::deviceAttachmentSpecs)
|
||||
{
|
||||
try {
|
||||
detachSenseDeviceReq(spec,
|
||||
[spec, &nTotal, &nSucceeded, &nFailed, caller = self](bool success) -> void
|
||||
{
|
||||
if (!success)
|
||||
{
|
||||
++nFailed;
|
||||
std::cerr << __func__ << ": Failed to detach device: "
|
||||
<< spec->deviceIdentifier << "\n";
|
||||
|
||||
caller->getIoService().post([]{});
|
||||
return;
|
||||
}
|
||||
|
||||
++nSucceeded;
|
||||
if (nSucceeded.load() + nFailed.load() != nTotal.load()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << __func__ << ": " << nSucceeded.load()
|
||||
<< " devices detached, "
|
||||
<< nFailed.load() << " devices failed\n";
|
||||
caller->getIoService().post([]{});
|
||||
});
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << __func__ << ": Exception: " << e.what() << "\n";
|
||||
++nFailed;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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())
|
||||
{
|
||||
/* Return early because the io_service is stopped. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (nTotal.load() != nSucceeded.load() + 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";
|
||||
}
|
||||
|
||||
} // namespace sense_api
|
||||
|
||||
Reference in New Issue
Block a user