816a047920
Async: Use new [Non]PostedAsyncCont and callOriginalCb This new hierarchy of classes gives us a central mechanism for managing both reply-posting and lockSpec unlocking. * callOriginalCb: Now uses a modern C++ variadic template design enabling it to handle both direct calling and std::bind() re-binding of an arbitrary number of arguments from the caller. This enables us to mostly eliminate the repeated, bespoke definitions of callOriginalCb littered throughout the codebase. We've also propagated these changes throughout the codebase in this patch.
152 lines
4.1 KiB
C++
152 lines
4.1 KiB
C++
#include <iostream>
|
|
#include <fstream>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <sstream>
|
|
#include <memory>
|
|
#include <opts.h>
|
|
#include <asynchronousContinuation.h>
|
|
#include <deviceManager/deviceManager.h>
|
|
#include <senseApis/senseApiManager.h>
|
|
#include <marionette/marionette.h>
|
|
|
|
namespace smo {
|
|
namespace device {
|
|
|
|
std::vector<std::shared_ptr<InteroceptorDevAttachmentSpec>>
|
|
DeviceManager::interoceptorDeviceSpecs;
|
|
std::vector<std::shared_ptr<ExtrospectorDevAttachmentSpec>>
|
|
DeviceManager::extrospectorDeviceSpecs;
|
|
std::vector<std::shared_ptr<DeviceAttachmentSpec>>
|
|
DeviceManager::deviceAttachmentSpecs;
|
|
std::vector<std::shared_ptr<Device>>
|
|
DeviceManager::devices;
|
|
|
|
const std::string DeviceManager::stringifyDeviceSpecs(void)
|
|
{
|
|
std::ostringstream oss;
|
|
|
|
for (const auto& spec : DeviceManager::interoceptorDeviceSpecs) {
|
|
oss << "Interoceptor " << spec->stringify();
|
|
}
|
|
|
|
for (const auto& spec : DeviceManager::extrospectorDeviceSpecs) {
|
|
oss << "Extrospector " << spec->stringify();
|
|
}
|
|
|
|
return oss.str();
|
|
}
|
|
|
|
class DeviceManager::NewDeviceAttachmentSpecInd
|
|
: public PostedAsynchronousContinuation<newDeviceAttachmentSpecIndCbFn>
|
|
{
|
|
public:
|
|
NewDeviceAttachmentSpecInd(
|
|
std::shared_ptr<DeviceAttachmentSpec> s,
|
|
const std::shared_ptr<ComponentThread> &caller,
|
|
newDeviceAttachmentSpecIndCbFn cb)
|
|
: PostedAsynchronousContinuation<newDeviceAttachmentSpecIndCbFn>(
|
|
caller, cb),
|
|
spec(s)
|
|
{}
|
|
|
|
public:
|
|
std::shared_ptr<DeviceAttachmentSpec> spec;
|
|
|
|
public:
|
|
void newDeviceAttachmentSpecInd1_posted(
|
|
[[maybe_unused]] std::shared_ptr<NewDeviceAttachmentSpecInd> context
|
|
)
|
|
{
|
|
sense_api::SenseApiManager::getInstance().attachSenseDeviceReq(
|
|
spec,
|
|
std::bind(
|
|
&NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd2,
|
|
context.get(), context,
|
|
std::placeholders::_1, std::placeholders::_2));
|
|
}
|
|
|
|
void newDeviceAttachmentSpecInd2(
|
|
[[maybe_unused]] std::shared_ptr<NewDeviceAttachmentSpecInd> context,
|
|
bool success,
|
|
std::shared_ptr<DeviceAttachmentSpec> deviceSpec
|
|
)
|
|
{
|
|
if (!success)
|
|
{
|
|
std::cerr << __func__ << ": Attach failed for device spec "
|
|
<< deviceSpec->stringify() << std::endl;
|
|
callOriginalCb(false, nullptr, deviceSpec);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
/** EXPLANATION:
|
|
* Remember that deviceAttachmentSpecs don't refer to devices, but
|
|
* rather to roles that a device can enact when attached to in the
|
|
* described manner. Therefore, it's possible for multiple DA specs
|
|
* to refer to the same device.
|
|
*
|
|
* That's why we need to ensure that the device doesn't already
|
|
* exist before trying to create a new device for it.
|
|
*/
|
|
std::shared_ptr<Device> device = nullptr;
|
|
for (const auto& existingDevice : devices)
|
|
{
|
|
if (existingDevice->deviceIdentifier != spec->deviceIdentifier)
|
|
{ continue; }
|
|
|
|
device = existingDevice;
|
|
break;
|
|
}
|
|
|
|
// If device doesn't exist, create a new one and add it
|
|
if (!device)
|
|
{
|
|
device = std::make_shared<Device>(spec->deviceIdentifier);
|
|
devices.push_back(device);
|
|
}
|
|
|
|
// Add DeviceAttachmentSpec to device's list
|
|
device->deviceAttachmentSpecs.push_back(spec);
|
|
|
|
// Add DeviceAttachmentSpec to DeviceManager's list
|
|
deviceAttachmentSpecs.push_back(spec);
|
|
|
|
// Callback with success
|
|
callOriginalCb(true, device, spec);
|
|
} catch (const std::exception& e) {
|
|
// Attach failed, callback with error
|
|
callOriginalCb(false, nullptr, spec);
|
|
}
|
|
}
|
|
};
|
|
|
|
void DeviceManager::newDeviceAttachmentSpecInd(
|
|
std::shared_ptr<DeviceAttachmentSpec> spec,
|
|
newDeviceAttachmentSpecIndCbFn callback)
|
|
{
|
|
// Check if a DeviceAttachmentSpec already matches
|
|
for (const auto& existingSpec : deviceAttachmentSpecs)
|
|
{
|
|
if (!(*existingSpec == *spec)) { continue; }
|
|
// Already exists, callback with error
|
|
callback(false, nullptr, spec);
|
|
return;
|
|
}
|
|
|
|
// Create async continuation
|
|
const auto& caller = ComponentThread::getSelf();
|
|
auto continuation = std::make_shared<NewDeviceAttachmentSpecInd>(
|
|
spec, caller, callback);
|
|
|
|
mrntt::mrntt.thread->getIoService().post(
|
|
std::bind(
|
|
&NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd1_posted,
|
|
continuation.get(), continuation));
|
|
}
|
|
|
|
} // namespace device
|
|
} // namespace smo
|