DevMgr: Move at/detachSenseDevs[FromSpecs] into DeviceMgr::
This is logically cleaner and it begins preparing our next set of restructuring changes. To wit: we're revamping the device manager to distinguish between devices and their roles.
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
#include <componentThread.h>
|
#include <componentThread.h>
|
||||||
#include <mind.h>
|
#include <mind.h>
|
||||||
#include <senseApis/senseApiManager.h>
|
#include <senseApis/senseApiManager.h>
|
||||||
|
#include <deviceManager/deviceManager.h>
|
||||||
|
|
||||||
namespace smo {
|
namespace smo {
|
||||||
namespace body {
|
namespace body {
|
||||||
@@ -77,8 +78,7 @@ public:
|
|||||||
std::cout << __func__ << ": About to attachAllSenseDevicesFromSpecs"
|
std::cout << __func__ << ": About to attachAllSenseDevicesFromSpecs"
|
||||||
<< '\n';
|
<< '\n';
|
||||||
}
|
}
|
||||||
sense_api::SenseApiManager::getInstance()
|
device::DeviceManager::getInstance().attachAllSenseDevicesFromSpecsReq(
|
||||||
.attachAllSenseDevicesFromSpecsReq(
|
|
||||||
{context, std::bind(
|
{context, std::bind(
|
||||||
&InitializeReq::initializeReq2,
|
&InitializeReq::initializeReq2,
|
||||||
context.get(), context,
|
context.get(), context,
|
||||||
@@ -117,7 +117,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Mrntt: About to detach all sense devices." << "\n";
|
std::cout << "Mrntt: About to detach all sense devices." << "\n";
|
||||||
sense_api::SenseApiManager::getInstance().detachAllSenseDevicesReq(
|
device::DeviceManager::getInstance().detachAllSenseDevicesReq(
|
||||||
{context, std::bind(
|
{context, std::bind(
|
||||||
&FinalizeReq::finalizeReq2,
|
&FinalizeReq::finalizeReq2,
|
||||||
context.get(), context,
|
context.get(), context,
|
||||||
|
|||||||
@@ -8,9 +8,11 @@
|
|||||||
#include <opts.h>
|
#include <opts.h>
|
||||||
#include <asynchronousContinuation.h>
|
#include <asynchronousContinuation.h>
|
||||||
#include <callback.h>
|
#include <callback.h>
|
||||||
|
#include <componentThread.h>
|
||||||
#include <deviceManager/deviceManager.h>
|
#include <deviceManager/deviceManager.h>
|
||||||
#include <senseApis/senseApiManager.h>
|
#include <senseApis/senseApiManager.h>
|
||||||
#include <marionette/marionette.h>
|
#include <marionette/marionette.h>
|
||||||
|
#include <mind.h>
|
||||||
|
|
||||||
namespace smo {
|
namespace smo {
|
||||||
namespace device {
|
namespace device {
|
||||||
@@ -60,7 +62,7 @@ public:
|
|||||||
[[maybe_unused]] std::shared_ptr<NewDeviceAttachmentSpecInd> context
|
[[maybe_unused]] std::shared_ptr<NewDeviceAttachmentSpecInd> context
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
sense_api::SenseApiManager::getInstance().attachSenseDeviceReq(
|
DeviceManager::getInstance().attachSenseDeviceReq(
|
||||||
spec,
|
spec,
|
||||||
{context, std::bind(
|
{context, std::bind(
|
||||||
&NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd2,
|
&NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd2,
|
||||||
@@ -148,5 +150,338 @@ void DeviceManager::newDeviceAttachmentSpecInd(
|
|||||||
continuation.get(), continuation));
|
continuation.get(), continuation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DeviceManager::AttachSenseDeviceReq
|
||||||
|
: public PostedAsynchronousContinuation<attachSenseDeviceReqCbFn>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AttachSenseDeviceReq(
|
||||||
|
const std::shared_ptr<DeviceAttachmentSpec>& spec,
|
||||||
|
const std::shared_ptr<ComponentThread> &caller,
|
||||||
|
Callback<attachSenseDeviceReqCbFn> cb)
|
||||||
|
: PostedAsynchronousContinuation<attachSenseDeviceReqCbFn>(
|
||||||
|
caller, cb),
|
||||||
|
spec(spec)
|
||||||
|
{}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void attachSenseDeviceReq1_posted(
|
||||||
|
[[maybe_unused]] std::shared_ptr<AttachSenseDeviceReq> context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (caller->id != ComponentThread::MRNTT)
|
||||||
|
{
|
||||||
|
std::cerr << std::string(__func__)
|
||||||
|
<< ": executed on non-mrntt thread: "
|
||||||
|
<< caller->name << std::endl;
|
||||||
|
callOriginalCb(false, spec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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 = sense_api::SenseApiManager::getInstance()
|
||||||
|
.getSenseApiLibByApiName(spec->api);
|
||||||
|
|
||||||
|
if (!libOpt)
|
||||||
|
{
|
||||||
|
std::cerr << std::string(__func__) + ": No library found for API '"
|
||||||
|
<< spec->api << "'" << std::endl;
|
||||||
|
callOriginalCb(false, spec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& lib = *libOpt.value();
|
||||||
|
if (!lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq)
|
||||||
|
{
|
||||||
|
std::cerr << std::string(__func__) + ": attachDeviceReq() is NULL "
|
||||||
|
"for library '" << lib.libraryPath << "'" << std::endl;
|
||||||
|
callOriginalCb(false, spec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** EXPLANATION:
|
||||||
|
* We pass in either the body or world thread here, depending on whether
|
||||||
|
* the device is an introspector (idev) or extrospector (edev).
|
||||||
|
*
|
||||||
|
* Introspectors are attached to the body thread; extrospectors are
|
||||||
|
* attached to the world thread.
|
||||||
|
*/
|
||||||
|
std::shared_ptr<ComponentThread> threadForAttachment;
|
||||||
|
if (spec->sensorType == 'e')
|
||||||
|
{
|
||||||
|
threadForAttachment = mind::globalMind->world.thread;
|
||||||
|
std::cout << __func__ << ": Attaching edev "
|
||||||
|
<< spec->deviceIdentifier << " to world thread" << "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
threadForAttachment = mind::globalMind->body.thread;
|
||||||
|
std::cout << __func__ << ": Attaching non-edev "
|
||||||
|
<< spec->deviceIdentifier << " to body thread" << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq(
|
||||||
|
spec, threadForAttachment,
|
||||||
|
{context, std::bind(
|
||||||
|
&AttachSenseDeviceReq::attachSenseDeviceReq2,
|
||||||
|
context.get(), context,
|
||||||
|
std::placeholders::_1, std::placeholders::_2)});
|
||||||
|
}
|
||||||
|
|
||||||
|
void attachSenseDeviceReq2(
|
||||||
|
[[maybe_unused]] std::shared_ptr<AttachSenseDeviceReq> context,
|
||||||
|
bool success,
|
||||||
|
std::shared_ptr<DeviceAttachmentSpec> deviceSpec
|
||||||
|
)
|
||||||
|
{
|
||||||
|
callOriginalCb(success, deviceSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void detachSenseDeviceReq1_posted(
|
||||||
|
[[maybe_unused]] std::shared_ptr<DetachSenseDeviceReq> context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (caller->id != ComponentThread::MRNTT)
|
||||||
|
{
|
||||||
|
std::cerr << std::string(__func__)
|
||||||
|
<< ": executed on non-mrntt thread: "
|
||||||
|
<< caller->name << std::endl;
|
||||||
|
callOriginalCb(false, spec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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 = sense_api::SenseApiManager::getInstance()
|
||||||
|
.getSenseApiLibByApiName(spec->api);
|
||||||
|
|
||||||
|
if (!libOpt)
|
||||||
|
{
|
||||||
|
std::cerr << std::string(__func__) + ": No library found for API '"
|
||||||
|
<< spec->api << "'" << std::endl;
|
||||||
|
callOriginalCb(false, spec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto& lib = *libOpt.value();
|
||||||
|
if (!lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq)
|
||||||
|
{
|
||||||
|
std::cerr << std::string(__func__) + ": detachDeviceReq() is NULL "
|
||||||
|
"for library '" << lib.libraryPath << "'" << std::endl;
|
||||||
|
callOriginalCb(false, spec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq(
|
||||||
|
spec,
|
||||||
|
{context, std::bind(
|
||||||
|
&DetachSenseDeviceReq::detachSenseDeviceReq2,
|
||||||
|
context.get(), context,
|
||||||
|
std::placeholders::_1, std::placeholders::_2)});
|
||||||
|
}
|
||||||
|
|
||||||
|
void detachSenseDeviceReq2(
|
||||||
|
[[maybe_unused]] std::shared_ptr<DetachSenseDeviceReq> context,
|
||||||
|
bool success,
|
||||||
|
std::shared_ptr<DeviceAttachmentSpec> deviceSpec
|
||||||
|
)
|
||||||
|
{
|
||||||
|
callOriginalCb(success, deviceSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::shared_ptr<DeviceAttachmentSpec> spec;
|
||||||
|
};
|
||||||
|
|
||||||
|
void DeviceManager::attachSenseDeviceReq(
|
||||||
|
const std::shared_ptr<DeviceAttachmentSpec>& spec,
|
||||||
|
Callback<attachSenseDeviceReqCbFn> cb
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const auto& caller = ComponentThread::getSelf();
|
||||||
|
auto request = std::make_shared<AttachSenseDeviceReq>(
|
||||||
|
spec, caller, cb);
|
||||||
|
|
||||||
|
mrntt::mrntt.thread->getIoService().post(
|
||||||
|
std::bind(
|
||||||
|
&AttachSenseDeviceReq::attachSenseDeviceReq1_posted,
|
||||||
|
request.get(), request));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceManager::detachSenseDeviceReq(
|
||||||
|
const std::shared_ptr<DeviceAttachmentSpec>& spec,
|
||||||
|
Callback<detachSenseDeviceReqCbFn> cb
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const auto& caller = ComponentThread::getSelf();
|
||||||
|
auto request = std::make_shared<DetachSenseDeviceReq>(
|
||||||
|
spec, caller, cb);
|
||||||
|
|
||||||
|
mrntt::mrntt.thread->getIoService().post(
|
||||||
|
std::bind(
|
||||||
|
&DetachSenseDeviceReq::detachSenseDeviceReq1_posted,
|
||||||
|
request.get(), request));
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeviceManager::AttachAllSenseDevicesFromSpecsReq
|
||||||
|
: public PostedAsynchronousContinuation<
|
||||||
|
attachAllSenseDevicesFromSpecsReqCbFn>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AttachAllSenseDevicesFromSpecsReq(
|
||||||
|
const unsigned int totalNSpecs,
|
||||||
|
const std::shared_ptr<ComponentThread>& caller,
|
||||||
|
Callback<attachAllSenseDevicesFromSpecsReqCbFn> cb)
|
||||||
|
: PostedAsynchronousContinuation<attachAllSenseDevicesFromSpecsReqCbFn>(
|
||||||
|
caller, cb),
|
||||||
|
loop(totalNSpecs)
|
||||||
|
{}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void attachAllSenseDevicesFromSpecsReq1_posted(
|
||||||
|
[[maybe_unused]] std::shared_ptr<AttachAllSenseDevicesFromSpecsReq>
|
||||||
|
context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
for (const auto& spec : DeviceManager::deviceAttachmentSpecs)
|
||||||
|
{
|
||||||
|
DeviceManager::getInstance().attachSenseDeviceReq(
|
||||||
|
spec,
|
||||||
|
{context, std::bind(
|
||||||
|
&AttachAllSenseDevicesFromSpecsReq::attachAllSenseDevicesFromSpecsReq2,
|
||||||
|
context.get(), context,
|
||||||
|
std::placeholders::_1, std::placeholders::_2)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback methods for the attachment sequence
|
||||||
|
void attachAllSenseDevicesFromSpecsReq2(
|
||||||
|
std::shared_ptr<AttachAllSenseDevicesFromSpecsReq> context,
|
||||||
|
bool success, std::shared_ptr<DeviceAttachmentSpec> spec
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
std::cerr << __func__ << ": Failed to attach device: "
|
||||||
|
<< spec->deviceIdentifier << "\n";
|
||||||
|
// Fallthrough.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context->loop.incrementSuccessOrFailureAndTestForCompletionDueTo(
|
||||||
|
success))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OptionParser::getOptions().verbose)
|
||||||
|
{
|
||||||
|
std::cout << __func__ << ": " << context->loop.nSucceeded.load()
|
||||||
|
<< " devices attached, "
|
||||||
|
<< context->loop.nFailed.load() << " devices failed\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
context->callOriginalCb(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
AsynchronousLoop loop;
|
||||||
|
};
|
||||||
|
|
||||||
|
void DeviceManager::attachAllSenseDevicesFromSpecsReq(
|
||||||
|
Callback<attachAllSenseDevicesFromSpecsReqCbFn> cb
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (DeviceManager::getInstance().deviceAttachmentSpecs.size() == 0)
|
||||||
|
{
|
||||||
|
AsynchronousLoop tmp(0);
|
||||||
|
cb.callbackFn(tmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& caller = ComponentThread::getSelf();
|
||||||
|
auto request = std::make_shared<AttachAllSenseDevicesFromSpecsReq>(
|
||||||
|
DeviceManager::getInstance().deviceAttachmentSpecs.size(),
|
||||||
|
caller, std::move(cb));
|
||||||
|
|
||||||
|
mrntt::mrntt.thread->getIoService().post(
|
||||||
|
std::bind(
|
||||||
|
&AttachAllSenseDevicesFromSpecsReq::attachAllSenseDevicesFromSpecsReq1_posted,
|
||||||
|
request.get(), request));
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeviceManager::DetachAllSenseDevicesReq
|
||||||
|
: public AttachAllSenseDevicesFromSpecsReq
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using AttachAllSenseDevicesFromSpecsReq::AttachAllSenseDevicesFromSpecsReq;
|
||||||
|
|
||||||
|
void detachAllSenseDevicesReq1_posted(
|
||||||
|
[[maybe_unused]] std::shared_ptr<DetachAllSenseDevicesReq> context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
for (const auto& spec : DeviceManager::deviceAttachmentSpecs)
|
||||||
|
{
|
||||||
|
DeviceManager::getInstance().detachSenseDeviceReq(
|
||||||
|
spec,
|
||||||
|
{context, std::bind(
|
||||||
|
&DetachAllSenseDevicesReq::detachAllSenseDevicesReq2,
|
||||||
|
context.get(), context,
|
||||||
|
std::placeholders::_1, std::placeholders::_2)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void detachAllSenseDevicesReq2(
|
||||||
|
std::shared_ptr<DetachAllSenseDevicesReq> context,
|
||||||
|
bool success, std::shared_ptr<DeviceAttachmentSpec> spec
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
std::cerr << __func__ << ": Failed to detach device: "
|
||||||
|
<< spec->deviceIdentifier << "\n";
|
||||||
|
// Fallthrough.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context->loop.incrementSuccessOrFailureAndTestForCompletionDueTo(
|
||||||
|
success))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OptionParser::getOptions().verbose)
|
||||||
|
{
|
||||||
|
std::cout << __func__ << ": " << context->loop.nSucceeded.load()
|
||||||
|
<< " devices detached, "
|
||||||
|
<< context->loop.nFailed.load() << " devices failed\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
context->callOriginalCb(loop);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void DeviceManager::detachAllSenseDevicesReq(
|
||||||
|
Callback<detachAllSenseDevicesReqCbFn> cb
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (DeviceManager::getInstance().deviceAttachmentSpecs.size() == 0)
|
||||||
|
{
|
||||||
|
AsynchronousLoop tmp(0);
|
||||||
|
cb.callbackFn(tmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& caller = ComponentThread::getSelf();
|
||||||
|
auto request = std::make_shared<DetachAllSenseDevicesReq>(
|
||||||
|
DeviceManager::getInstance().deviceAttachmentSpecs.size(),
|
||||||
|
caller, std::move(cb));
|
||||||
|
|
||||||
|
mrntt::mrntt.thread->getIoService().post(
|
||||||
|
std::bind(
|
||||||
|
&DetachAllSenseDevicesReq::detachAllSenseDevicesReq1_posted,
|
||||||
|
request.get(), request));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace device
|
} // namespace device
|
||||||
} // namespace smo
|
} // namespace smo
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <user/senseApiDesc.h>
|
||||||
#include <user/deviceAttachmentSpec.h>
|
#include <user/deviceAttachmentSpec.h>
|
||||||
|
#include <asynchronousLoop.h>
|
||||||
#include <deviceManager/device.h>
|
#include <deviceManager/device.h>
|
||||||
#include <callback.h>
|
#include <callback.h>
|
||||||
|
|
||||||
@@ -44,6 +46,27 @@ public:
|
|||||||
std::shared_ptr<DeviceAttachmentSpec> spec,
|
std::shared_ptr<DeviceAttachmentSpec> spec,
|
||||||
Callback<newDeviceAttachmentSpecIndCbFn> callback);
|
Callback<newDeviceAttachmentSpecIndCbFn> callback);
|
||||||
|
|
||||||
|
// Device attachment/detachment methods moved from SenseApiManager
|
||||||
|
typedef sense_api::sal_mlo_attachDeviceReqCbFn attachSenseDeviceReqCbFn;
|
||||||
|
typedef sense_api::sal_mlo_detachDeviceReqCbFn detachSenseDeviceReqCbFn;
|
||||||
|
|
||||||
|
void attachSenseDeviceReq(
|
||||||
|
const std::shared_ptr<DeviceAttachmentSpec>& spec,
|
||||||
|
Callback<attachSenseDeviceReqCbFn> cb);
|
||||||
|
void detachSenseDeviceReq(
|
||||||
|
const std::shared_ptr<DeviceAttachmentSpec>& spec,
|
||||||
|
Callback<detachSenseDeviceReqCbFn> cb);
|
||||||
|
|
||||||
|
typedef std::function<void(AsynchronousLoop &results)>
|
||||||
|
attachAllSenseDevicesFromSpecsReqCbFn;
|
||||||
|
typedef std::function<void(AsynchronousLoop &results)>
|
||||||
|
detachAllSenseDevicesReqCbFn;
|
||||||
|
|
||||||
|
void attachAllSenseDevicesFromSpecsReq(
|
||||||
|
Callback<attachAllSenseDevicesFromSpecsReqCbFn> cb);
|
||||||
|
void detachAllSenseDevicesReq(
|
||||||
|
Callback<detachAllSenseDevicesReqCbFn> cb);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceManager() = default;
|
DeviceManager() = default;
|
||||||
~DeviceManager() = default;
|
~DeviceManager() = default;
|
||||||
@@ -62,6 +85,10 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
class NewDeviceAttachmentSpecInd;
|
class NewDeviceAttachmentSpecInd;
|
||||||
|
class AttachSenseDeviceReq;
|
||||||
|
typedef AttachSenseDeviceReq DetachSenseDeviceReq;
|
||||||
|
class AttachAllSenseDevicesFromSpecsReq;
|
||||||
|
class DetachAllSenseDevicesReq;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace device
|
} // namespace device
|
||||||
|
|||||||
@@ -50,26 +50,6 @@ public:
|
|||||||
void initializeAllSenseApiLibs(void);
|
void initializeAllSenseApiLibs(void);
|
||||||
void finalizeAllSenseApiLibs(void);
|
void finalizeAllSenseApiLibs(void);
|
||||||
|
|
||||||
typedef sal_mlo_attachDeviceReqCbFn attachSenseDeviceReqCbFn;
|
|
||||||
typedef sal_mlo_detachDeviceReqCbFn detachSenseDeviceReqCbFn;
|
|
||||||
|
|
||||||
void attachSenseDeviceReq(
|
|
||||||
const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
|
|
||||||
Callback<attachSenseDeviceReqCbFn> cb);
|
|
||||||
void detachSenseDeviceReq(
|
|
||||||
const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
|
|
||||||
Callback<detachSenseDeviceReqCbFn> cb);
|
|
||||||
|
|
||||||
typedef std::function<void(AsynchronousLoop &results)>
|
|
||||||
attachAllSenseDevicesFromSpecsReqCbFn;
|
|
||||||
typedef std::function<void(AsynchronousLoop &results)>
|
|
||||||
detachAllSenseDevicesReqCbFn;
|
|
||||||
|
|
||||||
void attachAllSenseDevicesFromSpecsReq(
|
|
||||||
Callback<attachAllSenseDevicesFromSpecsReqCbFn> cb);
|
|
||||||
void detachAllSenseDevicesReq(
|
|
||||||
Callback<detachAllSenseDevicesReqCbFn> cb);
|
|
||||||
|
|
||||||
std::string stringifyLibs() const;
|
std::string stringifyLibs() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -81,11 +61,6 @@ private:
|
|||||||
|
|
||||||
std::vector<std::shared_ptr<SenseApiLib>> senseApiLibs;
|
std::vector<std::shared_ptr<SenseApiLib>> senseApiLibs;
|
||||||
|
|
||||||
class AttachSenseDeviceReq;
|
|
||||||
typedef AttachSenseDeviceReq DetachSenseDeviceReq;
|
|
||||||
class AttachAllSenseDevicesFromSpecsReq;
|
|
||||||
class DetachAllSenseDevicesReq;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::optional<std::string> searchForLibInSmoSearchPaths(
|
static std::optional<std::string> searchForLibInSmoSearchPaths(
|
||||||
const std::string& libraryPath);
|
const std::string& libraryPath);
|
||||||
|
|||||||
@@ -262,336 +262,6 @@ void SenseApiManager::finalizeAllSenseApiLibs(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SenseApiManager::AttachSenseDeviceReq
|
|
||||||
: public PostedAsynchronousContinuation<attachSenseDeviceReqCbFn>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AttachSenseDeviceReq(
|
|
||||||
const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
|
|
||||||
const std::shared_ptr<ComponentThread> &caller,
|
|
||||||
Callback<attachSenseDeviceReqCbFn> cb)
|
|
||||||
: PostedAsynchronousContinuation<attachSenseDeviceReqCbFn>(
|
|
||||||
caller, cb),
|
|
||||||
spec(spec)
|
|
||||||
{}
|
|
||||||
|
|
||||||
public:
|
|
||||||
void attachSenseDeviceReq1_posted(
|
|
||||||
[[maybe_unused]] std::shared_ptr<AttachSenseDeviceReq> context
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (caller->id != ComponentThread::MRNTT)
|
|
||||||
{
|
|
||||||
std::cerr << std::string(__func__)
|
|
||||||
<< ": executed on non-mrntt thread: "
|
|
||||||
<< caller->name << std::endl;
|
|
||||||
callOriginalCb(false, spec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 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 = SenseApiManager::getInstance().getSenseApiLibByApiName(
|
|
||||||
spec->api);
|
|
||||||
|
|
||||||
if (!libOpt)
|
|
||||||
{
|
|
||||||
std::cerr << std::string(__func__) + ": No library found for API '"
|
|
||||||
<< spec->api << "'" << std::endl;
|
|
||||||
callOriginalCb(false, spec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& lib = *libOpt.value();
|
|
||||||
if (!lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq)
|
|
||||||
{
|
|
||||||
std::cerr << std::string(__func__) + ": attachDeviceReq() is NULL "
|
|
||||||
"for library '" << lib.libraryPath << "'" << std::endl;
|
|
||||||
callOriginalCb(false, spec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** EXPLANATION:
|
|
||||||
* We pass in either the body or world thread here, depending on whether
|
|
||||||
* the device is an introspector (idev) or extrospector (edev).
|
|
||||||
*
|
|
||||||
* Introspectors are attached to the body thread; extrospectors are
|
|
||||||
* attached to the world thread.
|
|
||||||
*/
|
|
||||||
std::shared_ptr<ComponentThread> threadForAttachment;
|
|
||||||
if (spec->sensorType == 'e')
|
|
||||||
{
|
|
||||||
threadForAttachment = mind::globalMind->world.thread;
|
|
||||||
std::cout << __func__ << ": Attaching edev "
|
|
||||||
<< spec->deviceIdentifier << " to world thread" << "\n";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
threadForAttachment = mind::globalMind->body.thread;
|
|
||||||
std::cout << __func__ << ": Attaching non-edev "
|
|
||||||
<< spec->deviceIdentifier << " to body thread" << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq(
|
|
||||||
spec, threadForAttachment,
|
|
||||||
{context, std::bind(
|
|
||||||
&AttachSenseDeviceReq::attachSenseDeviceReq2,
|
|
||||||
context.get(), context,
|
|
||||||
std::placeholders::_1, std::placeholders::_2)});
|
|
||||||
}
|
|
||||||
|
|
||||||
void attachSenseDeviceReq2(
|
|
||||||
[[maybe_unused]] std::shared_ptr<AttachSenseDeviceReq> context,
|
|
||||||
bool success,
|
|
||||||
std::shared_ptr<device::DeviceAttachmentSpec> deviceSpec
|
|
||||||
)
|
|
||||||
{
|
|
||||||
callOriginalCb(success, deviceSpec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void detachSenseDeviceReq1_posted(
|
|
||||||
[[maybe_unused]] std::shared_ptr<DetachSenseDeviceReq> context
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (caller->id != ComponentThread::MRNTT)
|
|
||||||
{
|
|
||||||
std::cerr << std::string(__func__)
|
|
||||||
<< ": executed on non-mrntt thread: "
|
|
||||||
<< caller->name << std::endl;
|
|
||||||
callOriginalCb(false, spec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 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 = SenseApiManager::getInstance().getSenseApiLibByApiName(
|
|
||||||
spec->api);
|
|
||||||
if (!libOpt)
|
|
||||||
{
|
|
||||||
std::cerr << std::string(__func__) + ": No library found for API '"
|
|
||||||
<< spec->api << "'" << std::endl;
|
|
||||||
callOriginalCb(false, spec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto& lib = *libOpt.value();
|
|
||||||
if (!lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq)
|
|
||||||
{
|
|
||||||
std::cerr << std::string(__func__) + ": detachDeviceReq() is NULL "
|
|
||||||
"for library '" << lib.libraryPath << "'" << std::endl;
|
|
||||||
callOriginalCb(false, spec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq(
|
|
||||||
spec,
|
|
||||||
{context, std::bind(
|
|
||||||
&DetachSenseDeviceReq::detachSenseDeviceReq2,
|
|
||||||
context.get(), context,
|
|
||||||
std::placeholders::_1, std::placeholders::_2)});
|
|
||||||
}
|
|
||||||
|
|
||||||
void detachSenseDeviceReq2(
|
|
||||||
[[maybe_unused]] std::shared_ptr<DetachSenseDeviceReq> context,
|
|
||||||
bool success,
|
|
||||||
std::shared_ptr<device::DeviceAttachmentSpec> deviceSpec
|
|
||||||
)
|
|
||||||
{
|
|
||||||
callOriginalCb(success, deviceSpec);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
std::shared_ptr<device::DeviceAttachmentSpec> spec;
|
|
||||||
};
|
|
||||||
|
|
||||||
void SenseApiManager::attachSenseDeviceReq(
|
|
||||||
const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
|
|
||||||
Callback<attachSenseDeviceReqCbFn> cb
|
|
||||||
)
|
|
||||||
{
|
|
||||||
const auto& caller = ComponentThread::getSelf();
|
|
||||||
auto request = std::make_shared<AttachSenseDeviceReq>(
|
|
||||||
spec, caller, cb);
|
|
||||||
|
|
||||||
mrntt::mrntt.thread->getIoService().post(
|
|
||||||
std::bind(
|
|
||||||
&AttachSenseDeviceReq::attachSenseDeviceReq1_posted,
|
|
||||||
request.get(), request));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SenseApiManager::detachSenseDeviceReq(
|
|
||||||
const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
|
|
||||||
Callback<detachSenseDeviceReqCbFn> cb
|
|
||||||
)
|
|
||||||
{
|
|
||||||
const auto& caller = ComponentThread::getSelf();
|
|
||||||
auto request = std::make_shared<DetachSenseDeviceReq>(
|
|
||||||
spec, caller, cb);
|
|
||||||
|
|
||||||
mrntt::mrntt.thread->getIoService().post(
|
|
||||||
std::bind(
|
|
||||||
&DetachSenseDeviceReq::detachSenseDeviceReq1_posted,
|
|
||||||
request.get(), request));
|
|
||||||
}
|
|
||||||
|
|
||||||
class SenseApiManager::AttachAllSenseDevicesFromSpecsReq
|
|
||||||
: public PostedAsynchronousContinuation<
|
|
||||||
attachAllSenseDevicesFromSpecsReqCbFn>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AttachAllSenseDevicesFromSpecsReq(
|
|
||||||
const unsigned int totalNSpecs,
|
|
||||||
const std::shared_ptr<ComponentThread>& caller,
|
|
||||||
Callback<attachAllSenseDevicesFromSpecsReqCbFn> cb)
|
|
||||||
: PostedAsynchronousContinuation<attachAllSenseDevicesFromSpecsReqCbFn>(
|
|
||||||
caller, cb),
|
|
||||||
loop(totalNSpecs)
|
|
||||||
{}
|
|
||||||
|
|
||||||
public:
|
|
||||||
void attachAllSenseDevicesFromSpecsReq1_posted(
|
|
||||||
[[maybe_unused]] std::shared_ptr<AttachAllSenseDevicesFromSpecsReq> context
|
|
||||||
)
|
|
||||||
{
|
|
||||||
for (const auto& spec : device::DeviceManager::deviceAttachmentSpecs)
|
|
||||||
{
|
|
||||||
SenseApiManager::getInstance().attachSenseDeviceReq(
|
|
||||||
spec,
|
|
||||||
{context, std::bind(
|
|
||||||
&AttachAllSenseDevicesFromSpecsReq::attachAllSenseDevicesFromSpecsReq2,
|
|
||||||
context.get(), context,
|
|
||||||
std::placeholders::_1, std::placeholders::_2)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Callback methods for the attachment sequence
|
|
||||||
void attachAllSenseDevicesFromSpecsReq2(
|
|
||||||
std::shared_ptr<AttachAllSenseDevicesFromSpecsReq> context,
|
|
||||||
bool success, std::shared_ptr<device::DeviceAttachmentSpec> spec
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
std::cerr << __func__ << ": Failed to attach device: "
|
|
||||||
<< spec->deviceIdentifier << "\n";
|
|
||||||
// Fallthrough.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!context->loop.incrementSuccessOrFailureAndTestForCompletionDueTo(
|
|
||||||
success))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OptionParser::getOptions().verbose)
|
|
||||||
{
|
|
||||||
std::cout << __func__ << ": " << context->loop.nSucceeded.load()
|
|
||||||
<< " devices attached, "
|
|
||||||
<< context->loop.nFailed.load() << " devices failed\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
context->callOriginalCb(loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
AsynchronousLoop loop;
|
|
||||||
};
|
|
||||||
|
|
||||||
void SenseApiManager::attachAllSenseDevicesFromSpecsReq(
|
|
||||||
Callback<attachAllSenseDevicesFromSpecsReqCbFn> cb
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (device::DeviceManager::getInstance().deviceAttachmentSpecs.size() == 0)
|
|
||||||
{
|
|
||||||
AsynchronousLoop tmp(0);
|
|
||||||
cb.callbackFn(tmp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& caller = ComponentThread::getSelf();
|
|
||||||
auto request = std::make_shared<AttachAllSenseDevicesFromSpecsReq>(
|
|
||||||
device::DeviceManager::getInstance().deviceAttachmentSpecs.size(),
|
|
||||||
caller, std::move(cb));
|
|
||||||
|
|
||||||
mrntt::mrntt.thread->getIoService().post(
|
|
||||||
std::bind(
|
|
||||||
&AttachAllSenseDevicesFromSpecsReq::attachAllSenseDevicesFromSpecsReq1_posted,
|
|
||||||
request.get(), request));
|
|
||||||
}
|
|
||||||
|
|
||||||
class SenseApiManager::DetachAllSenseDevicesReq
|
|
||||||
: public AttachAllSenseDevicesFromSpecsReq
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using AttachAllSenseDevicesFromSpecsReq::AttachAllSenseDevicesFromSpecsReq;
|
|
||||||
|
|
||||||
void detachAllSenseDevicesReq1_posted(
|
|
||||||
[[maybe_unused]] std::shared_ptr<DetachAllSenseDevicesReq> context
|
|
||||||
)
|
|
||||||
{
|
|
||||||
for (const auto& spec : device::DeviceManager::deviceAttachmentSpecs)
|
|
||||||
{
|
|
||||||
SenseApiManager::getInstance().detachSenseDeviceReq(
|
|
||||||
spec,
|
|
||||||
{context, std::bind(
|
|
||||||
&DetachAllSenseDevicesReq::detachAllSenseDevicesReq2,
|
|
||||||
context.get(), context,
|
|
||||||
std::placeholders::_1, std::placeholders::_2)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void detachAllSenseDevicesReq2(
|
|
||||||
std::shared_ptr<DetachAllSenseDevicesReq> context,
|
|
||||||
bool success, std::shared_ptr<device::DeviceAttachmentSpec> spec
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
std::cerr << __func__ << ": Failed to detach device: "
|
|
||||||
<< spec->deviceIdentifier << "\n";
|
|
||||||
// Fallthrough.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!context->loop.incrementSuccessOrFailureAndTestForCompletionDueTo(
|
|
||||||
success))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OptionParser::getOptions().verbose)
|
|
||||||
{
|
|
||||||
std::cout << __func__ << ": " << context->loop.nSucceeded.load()
|
|
||||||
<< " devices detached, "
|
|
||||||
<< context->loop.nFailed.load() << " devices failed\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
context->callOriginalCb(loop);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void SenseApiManager::detachAllSenseDevicesReq(
|
|
||||||
Callback<detachAllSenseDevicesReqCbFn> cb
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (device::DeviceManager::getInstance().deviceAttachmentSpecs.size() == 0)
|
|
||||||
{
|
|
||||||
AsynchronousLoop tmp(0);
|
|
||||||
cb.callbackFn(tmp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& caller = ComponentThread::getSelf();
|
|
||||||
auto request = std::make_shared<DetachAllSenseDevicesReq>(
|
|
||||||
device::DeviceManager::getInstance().deviceAttachmentSpecs.size(),
|
|
||||||
caller, std::move(cb));
|
|
||||||
|
|
||||||
mrntt::mrntt.thread->getIoService().post(
|
|
||||||
std::bind(
|
|
||||||
&DetachAllSenseDevicesReq::detachAllSenseDevicesReq1_posted,
|
|
||||||
request.get(), request));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sense_api
|
} // namespace sense_api
|
||||||
} // namespace smo
|
} // namespace smo
|
||||||
|
|||||||
Reference in New Issue
Block a user