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
+10 -10
View File
@@ -3,8 +3,8 @@
#include <functional>
#include <optional>
#include <opts.h>
#include <spinscale/asynchronousContinuation.h>
#include <spinscale/callback.h>
#include <spinscale/cps/asynchronousContinuation.h>
#include <spinscale/cps/callback.h>
#include <user/senseApiDesc.h>
#include "protocol.h"
#include "core.h"
@@ -74,7 +74,7 @@ std::optional<std::shared_ptr<Device>> DeviceManager::getDevice(
// GetOrCreateDeviceReq nested class implementation
class DeviceManager::GetOrCreateDeviceReq
: public sscl::NonPostedAsynchronousContinuation<
: public sscl::cps::NonPostedAsynchronousContinuation<
livoxProto1_getOrCreateDeviceReqCbFn>
{
public:
@@ -86,8 +86,8 @@ public:
GetOrCreateDeviceReq(
DeviceManager& mgr,
std::shared_ptr<Device> device,
sscl::Callback<livoxProto1_getOrCreateDeviceReqCbFn> cb)
: sscl::NonPostedAsynchronousContinuation<
sscl::cps::Callback<livoxProto1_getOrCreateDeviceReqCbFn> cb)
: sscl::cps::NonPostedAsynchronousContinuation<
livoxProto1_getOrCreateDeviceReqCbFn>(std::move(cb)),
deviceManager(mgr), pendingDevice(device)
{}
@@ -132,7 +132,7 @@ void DeviceManager::getOrCreateDeviceReq(
int commandTimeoutMs, int retryDelayMs,
const std::string& smoIp, uint8_t smoSubnetNbits,
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort,
sscl::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback)
sscl::cps::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback)
{
// Validate smoIp format using Boost.Asio IPv4 validation
if (!smoIp.empty() && !comms::isValidIPv4(smoIp))
@@ -179,7 +179,7 @@ void DeviceManager::getOrCreateDeviceReq(
}
class DeviceManager::DestroyDeviceReq
: public sscl::NonPostedAsynchronousContinuation<
: public sscl::cps::NonPostedAsynchronousContinuation<
livoxProto1_destroyDeviceReqCbFn>
{
public:
@@ -190,8 +190,8 @@ public:
DestroyDeviceReq(
DeviceManager& mgr,
std::shared_ptr<Device> device,
sscl::Callback<livoxProto1_destroyDeviceReqCbFn> cb)
: sscl::NonPostedAsynchronousContinuation<
sscl::cps::Callback<livoxProto1_destroyDeviceReqCbFn> cb)
: sscl::cps::NonPostedAsynchronousContinuation<
livoxProto1_destroyDeviceReqCbFn>(std::move(cb)),
deviceManager(mgr), pendingDevice(device)
{}
@@ -220,7 +220,7 @@ public:
void DeviceManager::destroyDeviceReq(
std::shared_ptr<Device> dev,
sscl::Callback<livoxProto1_destroyDeviceReqCbFn> callback
sscl::cps::Callback<livoxProto1_destroyDeviceReqCbFn> callback
)
{
/** EXPLANATION:
+3 -3
View File
@@ -11,7 +11,7 @@
#include "broadcastListener.h"
#include "udpCommandDemuxer.h"
#include "livoxProto1.h"
#include <spinscale/callback.h>
#include <spinscale/cps/callback.h>
namespace livoxProto1 {
@@ -29,11 +29,11 @@ public:
int commandTimeoutMs, int retryDelayMs,
const std::string& smoIp, uint8_t smoSubnetNbits,
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort,
sscl::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback);
sscl::cps::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback);
void destroyDeviceReq(
std::shared_ptr<Device> device,
sscl::Callback<livoxProto1_destroyDeviceReqCbFn> callback);
sscl::cps::Callback<livoxProto1_destroyDeviceReqCbFn> callback);
std::optional<std::shared_ptr<Device>> getDevice(
const std::string &deviceIdentifier);
+39 -39
View File
@@ -17,8 +17,8 @@
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <opts.h>
#include <spinscale/asynchronousContinuation.h>
#include <spinscale/callback.h>
#include <spinscale/cps/asynchronousContinuation.h>
#include <spinscale/cps/callback.h>
#include "device.h"
#include "protocol.h"
#include "core.h"
@@ -124,15 +124,15 @@ Device::~Device()
* This class manages the overall device connection process including handshake and heartbeat setup
*/
class Device::ConnectReq
: public sscl::NonPostedAsynchronousContinuation<Device::connectReqCbFn>
: public sscl::cps::NonPostedAsynchronousContinuation<Device::connectReqCbFn>
{
private:
Device& device;
boost::asio::deadline_timer delayTimer;
public:
ConnectReq(Device& dev, sscl::Callback<Device::connectReqCbFn> cb)
: sscl::NonPostedAsynchronousContinuation<Device::connectReqCbFn>(
ConnectReq(Device& dev, sscl::cps::Callback<Device::connectReqCbFn> cb)
: sscl::cps::NonPostedAsynchronousContinuation<Device::connectReqCbFn>(
std::move(cb)), device(dev),
delayTimer(dev.componentThread->getIoService())
{}
@@ -216,7 +216,7 @@ public:
{ callOriginalCallback(false); }
};
void Device::connectReq(sscl::Callback<Device::connectReqCbFn> callback)
void Device::connectReq(sscl::cps::Callback<Device::connectReqCbFn> callback)
{
// Create the connection request object to hold state and callbacks
auto request = std::make_shared<ConnectReq>(*this, std::move(callback));
@@ -233,7 +233,7 @@ void Device::connectReq(sscl::Callback<Device::connectReqCbFn> callback)
}
class Device::ConnectToKnownDeviceReq
: public sscl::NonPostedAsynchronousContinuation<
: public sscl::cps::NonPostedAsynchronousContinuation<
Device::connectToKnownDeviceReqCbFn>
{
public:
@@ -241,8 +241,8 @@ public:
std::string deviceIP;
std::shared_ptr<livoxProto1::comms::DiscoveredDevice> deviceInfo;
ConnectToKnownDeviceReq(Device& dev, sscl::Callback<Device::connectToKnownDeviceReqCbFn> cb)
: sscl::NonPostedAsynchronousContinuation<
ConnectToKnownDeviceReq(Device& dev, sscl::cps::Callback<Device::connectToKnownDeviceReqCbFn> cb)
: sscl::cps::NonPostedAsynchronousContinuation<
Device::connectToKnownDeviceReqCbFn>(std::move(cb)), device(dev)
{}
@@ -269,7 +269,7 @@ public:
* broadcastListener.
*/
void Device::connectToKnownDeviceReq(
sscl::Callback<Device::connectToKnownDeviceReqCbFn> callback
sscl::cps::Callback<Device::connectToKnownDeviceReqCbFn> callback
)
{
// Create the connection request object to hold state and callbacks
@@ -336,7 +336,7 @@ void Device::connectToKnownDeviceReq(
}
class Device::ConnectByDeviceIdentifierReq
: public sscl::NonPostedAsynchronousContinuation<
: public sscl::cps::NonPostedAsynchronousContinuation<
Device::connectByDeviceIdentifierReqCbFn>
{
public:
@@ -344,8 +344,8 @@ public:
std::string deviceIP;
ConnectByDeviceIdentifierReq(
Device& dev, sscl::Callback<Device::connectByDeviceIdentifierReqCbFn> cb)
: sscl::NonPostedAsynchronousContinuation<
Device& dev, sscl::cps::Callback<Device::connectByDeviceIdentifierReqCbFn> cb)
: sscl::cps::NonPostedAsynchronousContinuation<
Device::connectByDeviceIdentifierReqCbFn>(
std::move(cb)), device(dev)
{}
@@ -370,7 +370,7 @@ public:
};
void Device::connectByDeviceIdentifierReq(
sscl::Callback<Device::connectByDeviceIdentifierReqCbFn> callback
sscl::cps::Callback<Device::connectByDeviceIdentifierReqCbFn> callback
)
{
/** EXPLANATION:
@@ -419,13 +419,13 @@ void Device::connectByDeviceIdentifierReq(
}
class Device::ExecuteHandshakeReq
: public sscl::NonPostedAsynchronousContinuation<
: public sscl::cps::NonPostedAsynchronousContinuation<
Device::executeHandshakeReqCbFn>
{
public:
friend void Device::executeHandshakeReq(
const std::string& deviceIP,
sscl::Callback<Device::executeHandshakeReqCbFn> callback);
sscl::cps::Callback<Device::executeHandshakeReqCbFn> callback);
enum class SocketState
{
@@ -459,8 +459,8 @@ public:
Device& dev, const std::string& deviceIP,
std::shared_ptr<boost::asio::posix::stream_descriptor>
&cmdEndpointFdDesc,
sscl::Callback<Device::executeHandshakeReqCbFn> cb)
: sscl::NonPostedAsynchronousContinuation<Device::executeHandshakeReqCbFn>(
sscl::cps::Callback<Device::executeHandshakeReqCbFn> cb)
: sscl::cps::NonPostedAsynchronousContinuation<Device::executeHandshakeReqCbFn>(
std::move(cb)),
device(dev), deviceIP(deviceIP),
cmdEndpointFdDesc(cmdEndpointFdDesc),
@@ -753,7 +753,7 @@ private:
void Device::executeHandshakeReq(
const std::string& deviceIP,
sscl::Callback<Device::executeHandshakeReqCbFn> callback
sscl::cps::Callback<Device::executeHandshakeReqCbFn> callback
)
{
// Get the command endpoint from the UdpCommandDemuxer
@@ -803,7 +803,7 @@ void Device::executeHandshakeReq(
}
}
void Device::disconnectReq(sscl::Callback<Device::disconnectReqCbFn> callback)
void Device::disconnectReq(sscl::cps::Callback<Device::disconnectReqCbFn> callback)
{
// Stop heartbeat first
stopHeartbeat();
@@ -1331,7 +1331,7 @@ std::optional<std::string> Device::getSmoIp(const std::string& deviceIP)
// Base class for both enable and disable pcloud data requests
template<typename CallbackType>
class EnDisablePcloudDataReq
: public sscl::NonPostedAsynchronousContinuation<CallbackType>
: public sscl::cps::NonPostedAsynchronousContinuation<CallbackType>
{
public:
enum class SocketState
@@ -1362,8 +1362,8 @@ public:
protected:
EnDisablePcloudDataReq(
Device& dev,
sscl::Callback<CallbackType> cb)
: sscl::NonPostedAsynchronousContinuation<CallbackType>(std::move(cb)),
sscl::cps::Callback<CallbackType> cb)
: sscl::cps::NonPostedAsynchronousContinuation<CallbackType>(std::move(cb)),
device(dev),
timeoutTimer(device.componentThread->getIoService())
{}
@@ -1608,11 +1608,11 @@ class Device::EnablePcloudDataReq
{
public:
friend void Device::enablePcloudDataReq(
sscl::Callback<Device::enablePcloudDataReqCbFn> callback);
sscl::cps::Callback<Device::enablePcloudDataReqCbFn> callback);
EnablePcloudDataReq(
Device& dev,
sscl::Callback<Device::enablePcloudDataReqCbFn> cb)
sscl::cps::Callback<Device::enablePcloudDataReqCbFn> cb)
: EnDisablePcloudDataReq<Device::enablePcloudDataReqCbFn>(dev, std::move(cb))
{}
@@ -1643,11 +1643,11 @@ class Device::DisablePcloudDataReq
{
public:
friend void Device::disablePcloudDataReq(
sscl::Callback<Device::disablePcloudDataReqCbFn> callback);
sscl::cps::Callback<Device::disablePcloudDataReqCbFn> callback);
DisablePcloudDataReq(
Device& dev,
sscl::Callback<Device::disablePcloudDataReqCbFn> cb)
sscl::cps::Callback<Device::disablePcloudDataReqCbFn> cb)
: EnDisablePcloudDataReq<Device::disablePcloudDataReqCbFn>(
dev, std::move(cb))
{}
@@ -1675,7 +1675,7 @@ private:
};
void Device::enablePcloudDataReq(
sscl::Callback<Device::enablePcloudDataReqCbFn> callback
sscl::cps::Callback<Device::enablePcloudDataReqCbFn> callback
)
{
auto request = std::make_shared<EnablePcloudDataReq>(
@@ -1702,7 +1702,7 @@ void Device::enablePcloudDataReq(
}
void Device::disablePcloudDataReq(
sscl::Callback<Device::disablePcloudDataReqCbFn> callback
sscl::cps::Callback<Device::disablePcloudDataReqCbFn> callback
)
{
auto request = std::make_shared<DisablePcloudDataReq>(
@@ -1858,7 +1858,7 @@ void Device::unregisterUdpCommandHandler(
// SetReturnModeReq continuation class
class Device::SetReturnModeReq
: public sscl::NonPostedAsynchronousContinuation<Device::setReturnModeReqCbFn>
: public sscl::cps::NonPostedAsynchronousContinuation<Device::setReturnModeReqCbFn>
{
public:
enum class SocketState
@@ -1890,12 +1890,12 @@ public:
public:
friend void Device::setReturnModeReq(
uint8_t returnMode,
sscl::Callback<Device::setReturnModeReqCbFn> callback);
sscl::cps::Callback<Device::setReturnModeReqCbFn> callback);
SetReturnModeReq(
Device& dev, uint8_t mode,
sscl::Callback<Device::setReturnModeReqCbFn> cb)
: sscl::NonPostedAsynchronousContinuation<Device::setReturnModeReqCbFn>(
sscl::cps::Callback<Device::setReturnModeReqCbFn> cb)
: sscl::cps::NonPostedAsynchronousContinuation<Device::setReturnModeReqCbFn>(
std::move(cb)),
device(dev), returnMode(mode),
timeoutTimer(device.componentThread->getIoService())
@@ -2107,7 +2107,7 @@ public:
// GetReturnModeReq continuation class
class Device::GetReturnModeReq
: public sscl::NonPostedAsynchronousContinuation<Device::getReturnModeReqCbFn>
: public sscl::cps::NonPostedAsynchronousContinuation<Device::getReturnModeReqCbFn>
{
public:
enum class SocketState
@@ -2137,12 +2137,12 @@ public:
public:
friend void Device::getReturnModeReq(
sscl::Callback<Device::getReturnModeReqCbFn> callback);
sscl::cps::Callback<Device::getReturnModeReqCbFn> callback);
GetReturnModeReq(
Device& dev,
sscl::Callback<Device::getReturnModeReqCbFn> cb)
: sscl::NonPostedAsynchronousContinuation<Device::getReturnModeReqCbFn>(
sscl::cps::Callback<Device::getReturnModeReqCbFn> cb)
: sscl::cps::NonPostedAsynchronousContinuation<Device::getReturnModeReqCbFn>(
std::move(cb)),
device(dev),
timeoutTimer(device.componentThread->getIoService())
@@ -2351,7 +2351,7 @@ public:
void Device::setReturnModeReq(
uint8_t returnMode,
sscl::Callback<Device::setReturnModeReqCbFn> callback
sscl::cps::Callback<Device::setReturnModeReqCbFn> callback
)
{
auto request = std::make_shared<SetReturnModeReq>(
@@ -2378,7 +2378,7 @@ void Device::setReturnModeReq(
}
void Device::getReturnModeReq(
sscl::Callback<Device::getReturnModeReqCbFn> callback
sscl::cps::Callback<Device::getReturnModeReqCbFn> callback
)
{
auto request = std::make_shared<GetReturnModeReq>(
+10 -10
View File
@@ -18,7 +18,7 @@
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include "protocol.h"
#include <spinscale/callback.h>
#include <spinscale/cps/callback.h>
#include <spinscale/spinLock.h>
// Custom hash function for std::pair<uint8_t, uint8_t>
@@ -163,20 +163,20 @@ public:
getReturnModeReqCbFn;
// Async connection methods
void connectReq(sscl::Callback<connectReqCbFn> callback);
void connectReq(sscl::cps::Callback<connectReqCbFn> callback);
void connectToKnownDeviceReq(
sscl::Callback<connectToKnownDeviceReqCbFn> callback);
sscl::cps::Callback<connectToKnownDeviceReqCbFn> callback);
void connectByDeviceIdentifierReq(
sscl::Callback<connectByDeviceIdentifierReqCbFn> callback);
sscl::cps::Callback<connectByDeviceIdentifierReqCbFn> callback);
void executeHandshakeReq(
const std::string& deviceIP,
sscl::Callback<executeHandshakeReqCbFn> callback);
void disconnectReq(sscl::Callback<disconnectReqCbFn> callback);
void enablePcloudDataReq(sscl::Callback<enablePcloudDataReqCbFn> callback);
void disablePcloudDataReq(sscl::Callback<disablePcloudDataReqCbFn> callback);
sscl::cps::Callback<executeHandshakeReqCbFn> callback);
void disconnectReq(sscl::cps::Callback<disconnectReqCbFn> callback);
void enablePcloudDataReq(sscl::cps::Callback<enablePcloudDataReqCbFn> callback);
void disablePcloudDataReq(sscl::cps::Callback<disablePcloudDataReqCbFn> callback);
void setReturnModeReq(
uint8_t returnMode, sscl::Callback<setReturnModeReqCbFn> callback);
void getReturnModeReq(sscl::Callback<getReturnModeReqCbFn> callback);
uint8_t returnMode, sscl::cps::Callback<setReturnModeReqCbFn> callback);
void getReturnModeReq(sscl::cps::Callback<getReturnModeReqCbFn> callback);
public:
comms::DiscoveredDevice discoveredDevice;
+6 -6
View File
@@ -1,6 +1,6 @@
#include <boostAsioLinkageFix.h>
#include <stdexcept>
#include <spinscale/callback.h>
#include <spinscale/cps/callback.h>
#include <boost/asio/posix/stream_descriptor.hpp>
#include "livoxProto1.h"
#include "device.h"
@@ -16,7 +16,7 @@ void livoxProto1_getOrCreateDeviceReq(
int commandTimeoutMs, int retryDelayMs,
const std::string& smoIp, uint8_t smoSubnetNbits,
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort,
sscl::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback
sscl::cps::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback
)
{
// Get the global DeviceManager instance
@@ -39,7 +39,7 @@ void livoxProto1_getOrCreateDeviceReq(
void livoxProto1_destroyDeviceReq(
std::shared_ptr<livoxProto1::Device> device,
sscl::Callback<livoxProto1_destroyDeviceReqCbFn> callback
sscl::cps::Callback<livoxProto1_destroyDeviceReqCbFn> callback
)
{
auto& protoState = livoxProto1::getProtoState();
@@ -67,7 +67,7 @@ void livoxProto1_exit(void)
void livoxProto1_device_enablePcloudDataReq(
std::shared_ptr<livoxProto1::Device> device,
sscl::Callback<livoxProto1_device_enablePcloudDataReqCbFn> callback
sscl::cps::Callback<livoxProto1_device_enablePcloudDataReqCbFn> callback
)
{
if (!device)
@@ -81,7 +81,7 @@ void livoxProto1_device_enablePcloudDataReq(
void livoxProto1_device_disablePcloudDataReq(
std::shared_ptr<livoxProto1::Device> device,
sscl::Callback<livoxProto1_device_disablePcloudDataReqCbFn> callback
sscl::cps::Callback<livoxProto1_device_disablePcloudDataReqCbFn> callback
)
{
if (!device)
@@ -95,7 +95,7 @@ void livoxProto1_device_disablePcloudDataReq(
void livoxProto1_device_getReturnModeReq(
std::shared_ptr<livoxProto1::Device> device,
sscl::Callback<livoxProto1_device_getReturnModeReqCbFn> callback
sscl::cps::Callback<livoxProto1_device_getReturnModeReqCbFn> callback
)
{
if (!device)
+6 -6
View File
@@ -6,7 +6,7 @@
#include <string>
#include <cstdint>
#include <functional>
#include <spinscale/callback.h>
#include <spinscale/cps/callback.h>
#include <boost/asio/posix/stream_descriptor.hpp>
// Forward declarations
@@ -64,30 +64,30 @@ typedef void livoxProto1_getOrCreateDeviceReqFn(
int commandTimeoutMs, int retryDelayMs,
const std::string& smoIp, uint8_t smoSubnetNbits,
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort,
sscl::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback);
sscl::cps::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback);
typedef std::function<void(bool success)> livoxProto1_destroyDeviceReqCbFn;
typedef void livoxProto1_destroyDeviceReqFn(
std::shared_ptr<livoxProto1::Device> device,
sscl::Callback<livoxProto1_destroyDeviceReqCbFn> callback);
sscl::cps::Callback<livoxProto1_destroyDeviceReqCbFn> callback);
typedef std::function<void(bool success)>
livoxProto1_device_enablePcloudDataReqCbFn;
typedef void livoxProto1_device_enablePcloudDataReqFn(
std::shared_ptr<livoxProto1::Device> device,
sscl::Callback<livoxProto1_device_enablePcloudDataReqCbFn> callback);
sscl::cps::Callback<livoxProto1_device_enablePcloudDataReqCbFn> callback);
typedef std::function<void(bool success)>
livoxProto1_device_disablePcloudDataReqCbFn;
typedef void livoxProto1_device_disablePcloudDataReqFn(
std::shared_ptr<livoxProto1::Device> device,
sscl::Callback<livoxProto1_device_disablePcloudDataReqCbFn> callback);
sscl::cps::Callback<livoxProto1_device_disablePcloudDataReqCbFn> callback);
typedef std::function<void(bool success, uint8_t returnMode)>
livoxProto1_device_getReturnModeReqCbFn;
typedef void livoxProto1_device_getReturnModeReqFn(
std::shared_ptr<livoxProto1::Device> device,
sscl::Callback<livoxProto1_device_getReturnModeReqCbFn> callback);
sscl::cps::Callback<livoxProto1_device_getReturnModeReqCbFn> callback);
typedef std::shared_ptr<boost::asio::posix::stream_descriptor>
livoxProto1_getPcloudDataFdDescFn(void);