Libspinscale: Initial top-level SMO port to coroutine framework

We haven't ported everything. Just the top-level methods. We'll
dig in to the leaf stuff later. Surprisingly, this all went without
any real difficulties.

Runs like a charm on first try.
This commit is contained in:
2026-05-24 16:12:29 -04:00
parent c539e6e924
commit cde2737876
44 changed files with 1296 additions and 1530 deletions
+15 -14
View File
@@ -7,7 +7,7 @@
#include <sstream>
#include <user/deviceAttachmentSpec.h>
#include <deviceManager/deviceRole.h>
#include <spinscale/qutex.h>
#include <spinscale/co/coQutex.h>
namespace smo {
namespace device {
@@ -15,25 +15,26 @@ namespace device {
class Device
{
public:
Device(const std::string& identifier)
: deviceIdentifier(identifier), qutex("Device-" + identifier)
explicit Device(const std::string& identifier)
: deviceIdentifier(identifier),
qutex("Device-" + identifier)
{}
std::string stringify() const
{
std::ostringstream os;
os << "Device Identifier: " << deviceIdentifier
<< ", Device Roles: " << deviceRoles.size() << std::endl;
for (const auto& deviceRole : deviceRoles) {
os << " " << deviceRole->deviceAttachmentSpec->stringify();
}
return os.str();
}
std::string stringify() const
{
std::ostringstream os;
os << "Device Identifier: " << deviceIdentifier
<< ", Device Roles: " << deviceRoles.size() << std::endl;
for (const auto& deviceRole : deviceRoles) {
os << " " << deviceRole->deviceAttachmentSpec->stringify();
}
return os.str();
}
public:
std::string deviceIdentifier;
std::vector<std::shared_ptr<DeviceRole>> deviceRoles;
sscl::Qutex qutex;
sscl::co::CoQutex qutex;
};
} // namespace device
+57 -68
View File
@@ -7,15 +7,16 @@
#include <opts.h>
#include <utility>
#include <iostream>
#include <functional>
#include <user/senseApiDesc.h>
#include <user/deviceAttachmentSpec.h>
#include <spinscale/asynchronousLoop.h>
#include <deviceManager/device.h>
#include <deviceManager/deviceRole.h>
#include <deviceManager/deviceReattacher.h>
#include <spinscale/callback.h>
#include <spinscale/qutex.h>
#include <cpsBoundary/stimBuffDeviceAReq.h>
#include <marionette/marionetteThread.h>
#include <spinscale/co/coQutex.h>
#include <spinscale/multiOperationResultSet.h>
#include <spinscale/sharedResourceGroup.h>
namespace smo {
namespace device {
@@ -25,11 +26,18 @@ class DeviceReattacher;
class DeviceManager
{
public:
static DeviceManager& getInstance()
{
static DeviceManager instance;
return instance;
}
struct DeviceAttachmentIndResult
{
bool success = false;
std::shared_ptr<DeviceRole> deviceRole;
std::shared_ptr<DeviceAttachmentSpec> deviceSpec;
};
static DeviceManager& getInstance()
{
static DeviceManager instance;
return instance;
}
void initialize(void)
{};
@@ -39,80 +47,61 @@ public:
void initializeDeviceReattacher();
void finalizeDeviceReattacher();
std::string readDapSpecFile(const std::string& filename);
void collateAllDapSpecs(void);
void parseAllDapSpecs(void);
std::string readDapSpecFile(const std::string& filename);
void collateAllDapSpecs(void);
void parseAllDapSpecs(void);
static const std::string stringifyDeviceSpecs(void);
static const std::string stringifyDeviceSpecs(void);
typedef std::function<void(
bool success, std::shared_ptr<DeviceRole> deviceRole,
std::shared_ptr<DeviceAttachmentSpec> deviceSpec)>
newDeviceAttachmentSpecIndCbFn;
typedef std::function<void(
bool success, std::shared_ptr<DeviceAttachmentSpec> deviceSpec)>
removeDeviceAttachmentSpecReqCbFn;
mrntt::MrnttViralPostingInvoker<DeviceAttachmentIndResult>
newDeviceAttachmentSpecIndCReq(const DeviceAttachmentSpec &spec);
void newDeviceAttachmentSpecInd(
const DeviceAttachmentSpec &spec,
sscl::Callback<newDeviceAttachmentSpecIndCbFn> callback);
void removeDeviceAttachmentSpecReq(
const DeviceAttachmentSpec &spec,
sscl::Callback<removeDeviceAttachmentSpecReqCbFn> callback);
mrntt::MrnttViralPostingInvoker<DeviceAttachmentIndResult>
removeDeviceAttachmentSpecCReq(const DeviceAttachmentSpec &spec);
// Device attachment/detachment methods moved from SenseApiManager
typedef stim_buff::sal_mlo_attachDeviceReqCbFn attachStimBuffDeviceReqCbFn;
typedef stim_buff::sal_mlo_detachDeviceReqCbFn detachStimBuffDeviceReqCbFn;
mrntt::MrnttViralPostingInvoker<cpsBoundary::StimBuffDeviceOpResult>
attachStimBuffDeviceCReq(
const std::shared_ptr<DeviceAttachmentSpec>& spec);
void attachStimBuffDeviceReq(
const std::shared_ptr<DeviceAttachmentSpec>& spec,
sscl::Callback<attachStimBuffDeviceReqCbFn> cb);
void detachStimBuffDeviceReq(
const std::shared_ptr<DeviceAttachmentSpec>& spec,
sscl::Callback<detachStimBuffDeviceReqCbFn> cb);
mrntt::MrnttViralPostingInvoker<cpsBoundary::StimBuffDeviceOpResult>
detachStimBuffDeviceCReq(
const std::shared_ptr<DeviceAttachmentSpec>& spec);
typedef std::function<void(sscl::AsynchronousLoop &results)>
attachAllUnattachedDevicesFromReqCbFn;
typedef std::function<void(sscl::AsynchronousLoop &results)>
detachAllAttachedDeviceRolesCbFn;
mrntt::MrnttViralPostingInvoker<sscl::MultiOperationResultSet>
attachAllUnattachedDevicesFromCReq(
const std::shared_ptr<std::vector<DeviceAttachmentSpec>> &specs);
void attachAllUnattachedDevicesFromReq(
const std::shared_ptr<std::vector<DeviceAttachmentSpec>> &specs,
sscl::Callback<attachAllUnattachedDevicesFromReqCbFn> cb);
void attachAllUnattachedDevicesFromKnownListReq(
sscl::Callback<attachAllUnattachedDevicesFromReqCbFn> cb);
void attachAllUnattachedDevicesFromCmdlineReq(
sscl::Callback<attachAllUnattachedDevicesFromReqCbFn> cb);
void detachAllAttachedDeviceRoles(
sscl::Callback<detachAllAttachedDeviceRolesCbFn> cb);
mrntt::MrnttViralPostingInvoker<sscl::MultiOperationResultSet>
attachAllUnattachedDevicesFromKnownListCReq();
mrntt::MrnttViralPostingInvoker<sscl::MultiOperationResultSet>
attachAllUnattachedDevicesFromCmdlineCReq();
mrntt::MrnttViralPostingInvoker<sscl::MultiOperationResultSet>
detachAllAttachedDeviceRolesCReq();
private:
DeviceManager()
: qutex("DeviceManager"), deviceReattacher(nullptr)
DeviceManager()
: s("DeviceManager")
{}
~DeviceManager();
DeviceManager(const DeviceManager&) = delete;
DeviceManager& operator=(const DeviceManager&) = delete;
~DeviceManager();
DeviceManager(const DeviceManager&) = delete;
DeviceManager& operator=(const DeviceManager&) = delete;
public:
sscl::Qutex qutex;
std::string allDapSpecs;
static std::vector<std::shared_ptr<DeviceAttachmentSpec>>
deviceAttachmentSpecs;
static std::vector<std::shared_ptr<Device>> devices;
static std::vector<std::shared_ptr<DeviceRole>> attachedDeviceRoles;
static std::vector<DeviceAttachmentSpec> commandLineDASpecs;
struct Resources
{
std::vector<std::shared_ptr<DeviceAttachmentSpec>> deviceAttachmentSpecs;
std::vector<std::shared_ptr<Device>> devices;
std::vector<std::shared_ptr<DeviceRole>> attachedDeviceRoles;
std::vector<DeviceAttachmentSpec> commandLineDASpecs;
std::string allDapSpecs;
};
sscl::SharedResourceGroup<sscl::co::CoQutex, Resources> s;
private:
std::unique_ptr<DeviceReattacher> deviceReattacher;
class NewDeviceAttachmentSpecInd;
class RemoveDeviceAttachmentSpecReq;
class AttachStimBuffDeviceReq;
typedef AttachStimBuffDeviceReq DetachStimBuffDeviceReq;
class AttachAllUnattachedDevicesFromReq;
class AttachAllUnattachedDevicesFromKnownListReq;
class DetachAllAttachedDeviceRoles;
};
} // namespace device
@@ -3,8 +3,14 @@
#include <boostAsioLinkageFix.h>
#include <atomic>
#include <chrono>
#include <exception>
#include <functional>
#include <memory>
#include <optional>
#include <boost/asio/deadline_timer.hpp>
#include <marionette/marionetteThread.h>
#include <spinscale/multiOperationResultSet.h>
#include <spinscale/spinLock.h>
namespace smo {
@@ -16,27 +22,35 @@ class DeviceManager;
class DeviceReattacher
{
public:
DeviceReattacher(
DeviceReattacher(
DeviceManager& parent, std::shared_ptr<sscl::ComponentThread> ioThread);
~DeviceReattacher() = default;
~DeviceReattacher() = default;
// Non-copyable
DeviceReattacher(const DeviceReattacher&) = delete;
DeviceReattacher& operator=(const DeviceReattacher&) = delete;
DeviceReattacher(const DeviceReattacher&) = delete;
DeviceReattacher& operator=(const DeviceReattacher&) = delete;
// Control methods
void start();
void stop();
// Control methods
void start();
void stop();
private:
void scheduleNextTimeout();
void onTimeout(const boost::system::error_code& error);
void scheduleNextTimeout();
void onTimeout(const boost::system::error_code& error);
void holdReattachCReq();
DeviceManager &parent;
std::shared_ptr<sscl::ComponentThread> ioThread;
sscl::SpinLock shouldContinueLock;
bool shouldContinue;
boost::asio::deadline_timer timer;
mrntt::MrnttNonViralPostingInvoker reattachKnownListCReq(
std::exception_ptr &exceptionPtr,
std::function<void()> callback);
DeviceManager &parent;
std::shared_ptr<sscl::ComponentThread> ioThread;
sscl::SpinLock shouldContinueLock;
bool shouldContinue;
boost::asio::deadline_timer timer;
std::exception_ptr reattachLifetimeExceptionPtr;
std::optional<mrntt::MrnttNonViralPostingInvoker> reattachCReqInvoker;
bool reattachOpInFlight = false;
std::chrono::steady_clock::time_point lastReattachReqTimestamp{};
};
} // namespace device