Async: add sh_ptr<ContinuationChainLink> to Callback<>

This change enables us to finally implement the tracing of
continuations backward from the point of acquisition for deadlock
debugging.
This commit is contained in:
2025-09-27 18:30:09 -04:00
parent 2212aec080
commit 782bcd4567
26 changed files with 384 additions and 269 deletions
+11 -10
View File
@@ -4,6 +4,7 @@
#include <optional> #include <optional>
#include <opts.h> #include <opts.h>
#include <asynchronousContinuation.h> #include <asynchronousContinuation.h>
#include <callback.h>
#include <user/senseApiDesc.h> #include <user/senseApiDesc.h>
#include "protocol.h" #include "protocol.h"
#include "core.h" #include "core.h"
@@ -84,7 +85,7 @@ public:
GetOrCreateDeviceReq( GetOrCreateDeviceReq(
DeviceManager& mgr, DeviceManager& mgr,
std::shared_ptr<Device> device, std::shared_ptr<Device> device,
livoxProto1_getOrCreateDeviceReqCbFn cb) smo::Callback<livoxProto1_getOrCreateDeviceReqCbFn> cb)
: smo::NonPostedAsynchronousContinuation< : smo::NonPostedAsynchronousContinuation<
livoxProto1_getOrCreateDeviceReqCbFn>(std::move(cb)), livoxProto1_getOrCreateDeviceReqCbFn>(std::move(cb)),
deviceManager(mgr), pendingDevice(device) deviceManager(mgr), pendingDevice(device)
@@ -130,7 +131,7 @@ void DeviceManager::getOrCreateDeviceReq(
int handshakeTimeoutMs, int retryDelayMs, int handshakeTimeoutMs, int retryDelayMs,
const std::string& smoIp, uint8_t smoSubnetNbits, const std::string& smoIp, uint8_t smoSubnetNbits,
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort, uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort,
livoxProto1_getOrCreateDeviceReqCbFn callback) smo::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback)
{ {
// Validate smoIp format using Boost.Asio IPv4 validation // Validate smoIp format using Boost.Asio IPv4 validation
if (!smoIp.empty() && !comms::isValidIPv4(smoIp)) if (!smoIp.empty() && !comms::isValidIPv4(smoIp))
@@ -154,7 +155,7 @@ void DeviceManager::getOrCreateDeviceReq(
if (existingDevice) if (existingDevice)
{ {
// Device already exists and is connected, return it // Device already exists and is connected, return it
callback(true, existingDevice.value()); callback.callbackFn(true, existingDevice.value());
return; return;
} }
@@ -171,9 +172,9 @@ void DeviceManager::getOrCreateDeviceReq(
// Start the connection process - only add to collection on success // Start the connection process - only add to collection on success
request->pendingDevice->connectReq( request->pendingDevice->connectReq(
std::bind( {request, std::bind(
&DeviceManager::GetOrCreateDeviceReq::getOrCreateDeviceReq1, &DeviceManager::GetOrCreateDeviceReq::getOrCreateDeviceReq1,
request.get(), request, std::placeholders::_1)); request.get(), request, std::placeholders::_1)});
} }
class DeviceManager::DestroyDeviceReq class DeviceManager::DestroyDeviceReq
@@ -188,7 +189,7 @@ public:
DestroyDeviceReq( DestroyDeviceReq(
DeviceManager& mgr, DeviceManager& mgr,
std::shared_ptr<Device> device, std::shared_ptr<Device> device,
livoxProto1_destroyDeviceReqCbFn cb) smo::Callback<livoxProto1_destroyDeviceReqCbFn> cb)
: smo::NonPostedAsynchronousContinuation< : smo::NonPostedAsynchronousContinuation<
livoxProto1_destroyDeviceReqCbFn>(std::move(cb)), livoxProto1_destroyDeviceReqCbFn>(std::move(cb)),
deviceManager(mgr), pendingDevice(device) deviceManager(mgr), pendingDevice(device)
@@ -218,7 +219,7 @@ public:
void DeviceManager::destroyDeviceReq( void DeviceManager::destroyDeviceReq(
std::shared_ptr<Device> dev, std::shared_ptr<Device> dev,
livoxProto1_destroyDeviceReqCbFn callback smo::Callback<livoxProto1_destroyDeviceReqCbFn> callback
) )
{ {
/** EXPLANATION: /** EXPLANATION:
@@ -230,7 +231,7 @@ void DeviceManager::destroyDeviceReq(
if (!device) if (!device)
{ {
callback(false); callback.callbackFn(false);
return; return;
} }
@@ -238,9 +239,9 @@ void DeviceManager::destroyDeviceReq(
*this, device, std::move(callback)); *this, device, std::move(callback));
device->disconnectReq( device->disconnectReq(
std::bind( {request, std::bind(
&DeviceManager::DestroyDeviceReq::destroyDeviceReq1, &DeviceManager::DestroyDeviceReq::destroyDeviceReq1,
request.get(), request, std::placeholders::_1)); request.get(), request, std::placeholders::_1)});
} }
void main(const std::shared_ptr<smo::ComponentThread> &componentThread, void main(const std::shared_ptr<smo::ComponentThread> &componentThread,
+3 -2
View File
@@ -10,6 +10,7 @@
#include "device.h" #include "device.h"
#include "broadcastListener.h" #include "broadcastListener.h"
#include "livoxProto1.h" #include "livoxProto1.h"
#include <callback.h>
namespace livoxProto1 { namespace livoxProto1 {
@@ -27,11 +28,11 @@ public:
int handshakeTimeoutMs, int retryDelayMs, int handshakeTimeoutMs, int retryDelayMs,
const std::string& smoIp, uint8_t smoSubnetNbits, const std::string& smoIp, uint8_t smoSubnetNbits,
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort, uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort,
livoxProto1_getOrCreateDeviceReqCbFn callback); smo::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback);
void destroyDeviceReq( void destroyDeviceReq(
std::shared_ptr<Device> device, std::shared_ptr<Device> device,
livoxProto1_destroyDeviceReqCbFn callback); smo::Callback<livoxProto1_destroyDeviceReqCbFn> callback);
std::optional<std::shared_ptr<Device>> getDevice( std::optional<std::shared_ptr<Device>> getDevice(
const std::string &deviceIdentifier); const std::string &deviceIdentifier);
+28 -24
View File
@@ -16,6 +16,7 @@
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <opts.h> #include <opts.h>
#include <asynchronousContinuation.h> #include <asynchronousContinuation.h>
#include <callback.h>
#include "device.h" #include "device.h"
#include "protocol.h" #include "protocol.h"
#include "core.h" #include "core.h"
@@ -127,7 +128,7 @@ private:
std::unique_ptr<boost::asio::deadline_timer> retryTimer; std::unique_ptr<boost::asio::deadline_timer> retryTimer;
public: public:
ConnectReq(Device& dev, Device::connectReqCbFn cb) ConnectReq(Device& dev, smo::Callback<Device::connectReqCbFn> cb)
: smo::NonPostedAsynchronousContinuation<Device::connectReqCbFn>( : smo::NonPostedAsynchronousContinuation<Device::connectReqCbFn>(
std::move(cb)), device(dev) std::move(cb)), device(dev)
{} {}
@@ -160,9 +161,9 @@ public:
// Try direct connect by device identifier // Try direct connect by device identifier
context->device.connectByDeviceIdentifierReq( context->device.connectByDeviceIdentifierReq(
std::bind(&ConnectReq::connectReq2, context.get(), context, {context, std::bind(&ConnectReq::connectReq2, context.get(), context,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3)); std::placeholders::_3)});
} }
void connectReq2( void connectReq2(
@@ -219,9 +220,9 @@ public:
} }
context->device.connectToKnownDeviceReq( context->device.connectToKnownDeviceReq(
std::bind(&ConnectReq::connectReq4, context.get(), context, {context, std::bind(&ConnectReq::connectReq4, context.get(), context,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3)); std::placeholders::_3)});
} }
void connectReq4( void connectReq4(
@@ -243,7 +244,7 @@ public:
} }
}; };
void Device::connectReq(Device::connectReqCbFn callback) void Device::connectReq(smo::Callback<Device::connectReqCbFn> callback)
{ {
// Create the connection request object to hold state and callbacks // Create the connection request object to hold state and callbacks
auto request = std::make_shared<ConnectReq>(*this, std::move(callback)); auto request = std::make_shared<ConnectReq>(*this, std::move(callback));
@@ -254,10 +255,10 @@ void Device::connectReq(Device::connectReqCbFn callback)
} }
connectToKnownDeviceReq( connectToKnownDeviceReq(
std::bind( {request, std::bind(
&ConnectReq::connectReq1, request.get(), request, &ConnectReq::connectReq1, request.get(), request,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3)); std::placeholders::_3)});
} }
class Device::ConnectToKnownDeviceReq class Device::ConnectToKnownDeviceReq
@@ -269,7 +270,7 @@ public:
std::string deviceIP; std::string deviceIP;
std::shared_ptr<livoxProto1::comms::DiscoveredDevice> deviceInfo; std::shared_ptr<livoxProto1::comms::DiscoveredDevice> deviceInfo;
ConnectToKnownDeviceReq(Device& dev, Device::connectToKnownDeviceReqCbFn cb) ConnectToKnownDeviceReq(Device& dev, smo::Callback<Device::connectToKnownDeviceReqCbFn> cb)
: smo::NonPostedAsynchronousContinuation< : smo::NonPostedAsynchronousContinuation<
Device::connectToKnownDeviceReqCbFn>(std::move(cb)), device(dev) Device::connectToKnownDeviceReqCbFn>(std::move(cb)), device(dev)
{} {}
@@ -297,7 +298,7 @@ public:
* broadcastListener. * broadcastListener.
*/ */
void Device::connectToKnownDeviceReq( void Device::connectToKnownDeviceReq(
Device::connectToKnownDeviceReqCbFn callback smo::Callback<Device::connectToKnownDeviceReqCbFn> callback
) )
{ {
// Create the connection request object to hold state and callbacks // Create the connection request object to hold state and callbacks
@@ -357,10 +358,10 @@ void Device::connectToKnownDeviceReq(
// Execute handshake with the known device using async method // Execute handshake with the known device using async method
request->device.executeHandshakeReq( request->device.executeHandshakeReq(
request->deviceIP, request->deviceIP,
std::bind( {request, std::bind(
&ConnectToKnownDeviceReq::connectToKnownDeviceReq1, &ConnectToKnownDeviceReq::connectToKnownDeviceReq1,
request.get(), request, request.get(), request,
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2)});
} }
class Device::ConnectByDeviceIdentifierReq class Device::ConnectByDeviceIdentifierReq
@@ -372,7 +373,7 @@ public:
std::string deviceIP; std::string deviceIP;
ConnectByDeviceIdentifierReq( ConnectByDeviceIdentifierReq(
Device& dev, Device::connectByDeviceIdentifierReqCbFn cb) Device& dev, smo::Callback<Device::connectByDeviceIdentifierReqCbFn> cb)
: smo::NonPostedAsynchronousContinuation< : smo::NonPostedAsynchronousContinuation<
Device::connectByDeviceIdentifierReqCbFn>( Device::connectByDeviceIdentifierReqCbFn>(
std::move(cb)), device(dev) std::move(cb)), device(dev)
@@ -398,7 +399,7 @@ public:
}; };
void Device::connectByDeviceIdentifierReq( void Device::connectByDeviceIdentifierReq(
Device::connectByDeviceIdentifierReqCbFn callback smo::Callback<Device::connectByDeviceIdentifierReqCbFn> callback
) )
{ {
/** EXPLANATION: /** EXPLANATION:
@@ -415,7 +416,7 @@ void Device::connectByDeviceIdentifierReq(
// Check if smoIp is provided - required for heuristic construction // Check if smoIp is provided - required for heuristic construction
if (smoIp.empty()) if (smoIp.empty())
{ {
callback(false, "", -1); callback.callbackFn(false, "", -1);
return; return;
} }
@@ -440,10 +441,10 @@ void Device::connectByDeviceIdentifierReq(
// Execute handshake using async method // Execute handshake using async method
request->device.executeHandshakeReq( request->device.executeHandshakeReq(
request->deviceIP, request->deviceIP,
std::bind( {request, std::bind(
&ConnectByDeviceIdentifierReq::connectByDeviceIdentifierReq1, &ConnectByDeviceIdentifierReq::connectByDeviceIdentifierReq1,
request.get(), request, request.get(), request,
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2)});
} }
class Device::ExecuteHandshakeReq class Device::ExecuteHandshakeReq
@@ -452,7 +453,8 @@ class Device::ExecuteHandshakeReq
{ {
public: public:
friend void Device::executeHandshakeReq( friend void Device::executeHandshakeReq(
const std::string& deviceIP, Device::executeHandshakeReqCbFn callback); const std::string& deviceIP,
smo::Callback<Device::executeHandshakeReqCbFn> callback);
enum class SocketState enum class SocketState
{ {
@@ -484,7 +486,7 @@ public:
public: public:
ExecuteHandshakeReq( ExecuteHandshakeReq(
Device& dev, const std::string& deviceIP, Device& dev, const std::string& deviceIP,
Device::executeHandshakeReqCbFn cb) smo::Callback<Device::executeHandshakeReqCbFn> cb)
: smo::NonPostedAsynchronousContinuation<Device::executeHandshakeReqCbFn>( : smo::NonPostedAsynchronousContinuation<Device::executeHandshakeReqCbFn>(
std::move(cb)), std::move(cb)),
device(dev), deviceIP(deviceIP), device(dev), deviceIP(deviceIP),
@@ -650,7 +652,8 @@ private:
*/ */
handshakeFdDesc.async_wait( handshakeFdDesc.async_wait(
boost::asio::posix::stream_descriptor::wait_read, boost::asio::posix::stream_descriptor::wait_read,
std::bind(&ExecuteHandshakeReq::executeHandshakeReq1_2, this, std::bind(
&ExecuteHandshakeReq::executeHandshakeReq1_2, this,
request, request,
std::placeholders::_1)); std::placeholders::_1));
} }
@@ -830,7 +833,8 @@ private:
}; };
void Device::executeHandshakeReq( void Device::executeHandshakeReq(
const std::string& deviceIP, Device::executeHandshakeReqCbFn callback const std::string& deviceIP,
smo::Callback<Device::executeHandshakeReqCbFn> callback
) )
{ {
// Create the handshake request object to hold state and callbacks // Create the handshake request object to hold state and callbacks
@@ -866,7 +870,7 @@ void Device::executeHandshakeReq(
} }
} }
void Device::disconnectReq(Device::disconnectReqCbFn callback) void Device::disconnectReq(smo::Callback<Device::disconnectReqCbFn> callback)
{ {
// Stop heartbeat first // Stop heartbeat first
heartbeatActive.store(false); heartbeatActive.store(false);
@@ -875,7 +879,7 @@ void Device::disconnectReq(Device::disconnectReqCbFn callback)
{ {
std::cout << __func__ << ": No heartbeat socket available, skipping " std::cout << __func__ << ": No heartbeat socket available, skipping "
"disconnect message" << std::endl; "disconnect message" << std::endl;
callback(true); callback.callbackFn(true);
return; return;
} }
@@ -911,7 +915,7 @@ void Device::disconnectReq(Device::disconnectReqCbFn callback)
// Close the heartbeat socket // Close the heartbeat socket
close(heartbeatFd); close(heartbeatFd);
heartbeatFd = -1; heartbeatFd = -1;
callback(true); callback.callbackFn(true);
} }
std::string Device::generateClientDeviceIpFromSerialNumber( std::string Device::generateClientDeviceIpFromSerialNumber(
+8 -5
View File
@@ -13,6 +13,7 @@
#include <unistd.h> #include <unistd.h>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "protocol.h" #include "protocol.h"
#include <callback.h>
// Forward declaration // Forward declaration
namespace smo { namespace smo {
@@ -111,13 +112,15 @@ public:
typedef std::function<void(bool success)> disconnectReqCbFn; typedef std::function<void(bool success)> disconnectReqCbFn;
// Async connection methods // Async connection methods
void connectReq(connectReqCbFn callback); void connectReq(smo::Callback<connectReqCbFn> callback);
void connectToKnownDeviceReq(connectToKnownDeviceReqCbFn callback); void connectToKnownDeviceReq(
smo::Callback<connectToKnownDeviceReqCbFn> callback);
void connectByDeviceIdentifierReq( void connectByDeviceIdentifierReq(
connectByDeviceIdentifierReqCbFn callback); smo::Callback<connectByDeviceIdentifierReqCbFn> callback);
void executeHandshakeReq( void executeHandshakeReq(
const std::string& deviceIP, executeHandshakeReqCbFn callback); const std::string& deviceIP,
void disconnectReq(disconnectReqCbFn callback); smo::Callback<executeHandshakeReqCbFn> callback);
void disconnectReq(smo::Callback<disconnectReqCbFn> callback);
// Heartbeat state // Heartbeat state
std::unique_ptr<boost::asio::deadline_timer> heartbeatTimer; std::unique_ptr<boost::asio::deadline_timer> heartbeatTimer;
+3 -2
View File
@@ -1,4 +1,5 @@
#include <stdexcept> #include <stdexcept>
#include <callback.h>
#include "livoxProto1.h" #include "livoxProto1.h"
#include "device.h" #include "device.h"
#include "core.h" #include "core.h"
@@ -12,7 +13,7 @@ void livoxProto1_getOrCreateDeviceReq(
int handshakeTimeoutMs, int retryDelayMs, int handshakeTimeoutMs, int retryDelayMs,
const std::string& smoIp, uint8_t smoSubnetNbits, const std::string& smoIp, uint8_t smoSubnetNbits,
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort, uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort,
livoxProto1_getOrCreateDeviceReqCbFn callback smo::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback
) )
{ {
// Get the global DeviceManager instance // Get the global DeviceManager instance
@@ -35,7 +36,7 @@ void livoxProto1_getOrCreateDeviceReq(
void livoxProto1_destroyDeviceReq( void livoxProto1_destroyDeviceReq(
std::shared_ptr<livoxProto1::Device> device, std::shared_ptr<livoxProto1::Device> device,
livoxProto1_destroyDeviceReqCbFn callback smo::Callback<livoxProto1_destroyDeviceReqCbFn> callback
) )
{ {
auto& protoState = livoxProto1::getProtoState(); auto& protoState = livoxProto1::getProtoState();
+3 -2
View File
@@ -5,6 +5,7 @@
#include <string> #include <string>
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include <callback.h>
// Forward declarations // Forward declarations
namespace smo { namespace smo {
@@ -59,12 +60,12 @@ typedef void livoxProto1_getOrCreateDeviceReqFn(
int handshakeTimeoutMs, int retryDelayMs, int handshakeTimeoutMs, int retryDelayMs,
const std::string& smoIp, uint8_t smoSubnetNbits, const std::string& smoIp, uint8_t smoSubnetNbits,
uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort, uint16_t dataPort, uint16_t cmdPort, uint16_t imuPort,
livoxProto1_getOrCreateDeviceReqCbFn callback); smo::Callback<livoxProto1_getOrCreateDeviceReqCbFn> callback);
typedef std::function<void(bool success)> livoxProto1_destroyDeviceReqCbFn; typedef std::function<void(bool success)> livoxProto1_destroyDeviceReqCbFn;
typedef void livoxProto1_destroyDeviceReqFn( typedef void livoxProto1_destroyDeviceReqFn(
std::shared_ptr<livoxProto1::Device> device, std::shared_ptr<livoxProto1::Device> device,
livoxProto1_destroyDeviceReqCbFn callback); smo::Callback<livoxProto1_destroyDeviceReqCbFn> callback);
livoxProto1_mainFn livoxProto1_main; livoxProto1_mainFn livoxProto1_main;
+18 -11
View File
@@ -6,6 +6,8 @@
#include <exception> #include <exception>
#include <componentThread.h> #include <componentThread.h>
#include <lockSet.h> #include <lockSet.h>
#include <callback.h>
#include <asynchronousContinuationChainLink.h>
namespace smo { namespace smo {
@@ -21,10 +23,11 @@ namespace smo {
*/ */
template <class OriginalCbFnT> template <class OriginalCbFnT>
class AsynchronousContinuation class AsynchronousContinuation
: public AsynchronousContinuationChainLink
{ {
public: public:
explicit AsynchronousContinuation(OriginalCbFnT originalCbFn) explicit AsynchronousContinuation(Callback<OriginalCbFnT> originalCb)
: originalCbFn(std::move(originalCbFn)) : originalCallback(std::move(originalCb))
{} {}
/** EXPLANATION: /** EXPLANATION:
@@ -65,7 +68,7 @@ public:
} }
public: public:
OriginalCbFnT originalCbFn; Callback<OriginalCbFnT> originalCallback;
std::exception_ptr exception; std::exception_ptr exception;
}; };
@@ -84,8 +87,9 @@ class NonPostedAsynchronousContinuation
: public AsynchronousContinuation<OriginalCbFnT> : public AsynchronousContinuation<OriginalCbFnT>
{ {
public: public:
explicit NonPostedAsynchronousContinuation(OriginalCbFnT originalCbFn) explicit NonPostedAsynchronousContinuation(
: AsynchronousContinuation<OriginalCbFnT>(originalCbFn) Callback<OriginalCbFnT> originalCb)
: AsynchronousContinuation<OriginalCbFnT>(originalCb)
{} {}
/** /**
@@ -100,10 +104,11 @@ public:
template<typename... Args> template<typename... Args>
void callOriginalCb(Args&&... args) void callOriginalCb(Args&&... args)
{ {
if (AsynchronousContinuation<OriginalCbFnT>::originalCbFn) if (AsynchronousContinuation<OriginalCbFnT>::originalCallback
.callbackFn)
{ {
AsynchronousContinuation<OriginalCbFnT>::originalCbFn( AsynchronousContinuation<OriginalCbFnT>::originalCallback
std::forward<Args>(args)...); .callbackFn(std::forward<Args>(args)...);
} }
} }
}; };
@@ -115,7 +120,7 @@ class PostedAsynchronousContinuation
public: public:
PostedAsynchronousContinuation( PostedAsynchronousContinuation(
const std::shared_ptr<ComponentThread> &caller, const std::shared_ptr<ComponentThread> &caller,
OriginalCbFnT originalCbFn) Callback<OriginalCbFnT> originalCbFn)
: AsynchronousContinuation<OriginalCbFnT>(originalCbFn), : AsynchronousContinuation<OriginalCbFnT>(originalCbFn),
caller(caller) caller(caller)
{} {}
@@ -123,11 +128,13 @@ public:
template<typename... Args> template<typename... Args>
void callOriginalCb(Args&&... args) void callOriginalCb(Args&&... args)
{ {
if (AsynchronousContinuation<OriginalCbFnT>::originalCbFn) if (AsynchronousContinuation<OriginalCbFnT>::originalCallback
.callbackFn)
{ {
caller->getIoService().post( caller->getIoService().post(
std::bind( std::bind(
AsynchronousContinuation<OriginalCbFnT>::originalCbFn, AsynchronousContinuation<OriginalCbFnT>::originalCallback
.callbackFn,
std::forward<Args>(args)...)); std::forward<Args>(args)...));
} }
} }
@@ -0,0 +1,25 @@
#ifndef ASYNCHRONOUS_CONTINUATION_CHAIN_LINK_H
#define ASYNCHRONOUS_CONTINUATION_CHAIN_LINK_H
#include <memory>
namespace smo {
/**
* @brief Base class for all asynchronous continuation chain links
*
* This non-template base class provides type erasure for the continuation
* chain, allowing RTTI and dynamic casting when walking the chain.
*
* The chain walking logic can use dynamic_cast to determine the most
* derived type and perform appropriate operations.
*/
class AsynchronousContinuationChainLink
{
public:
virtual ~AsynchronousContinuationChainLink() = default;
};
} // namespace smo
#endif // ASYNCHRONOUS_CONTINUATION_CHAIN_LINK_H
+6 -13
View File
@@ -7,7 +7,7 @@
namespace smo { namespace smo {
// Forward declaration // Forward declaration
class AsyncContinuation; class AsynchronousContinuationChainLink;
/** /**
* @brief Callback class that wraps a function and its caller continuation * @brief Callback class that wraps a function and its caller continuation
@@ -15,23 +15,16 @@ class AsyncContinuation;
* This class provides a way to pass both a callback function and the * This class provides a way to pass both a callback function and the
* caller's continuation in a single object, enabling deadlock detection * caller's continuation in a single object, enabling deadlock detection
* by walking the chain of continuations. * by walking the chain of continuations.
*
* Usage: Callback<CbFnT>{context, std::bind(...)}
*/ */
template<typename CbFnT> template<typename CbFnT>
class Callback class Callback
{ {
public: public:
/** // Aggregate initialization allows: Callback<CbFnT>{context, std::bind(...)}
* @brief Constructor std::shared_ptr<AsynchronousContinuationChainLink> callerContinuation;
* @param caller The caller's continuation CbFnT callbackFn;
* @param cb The callback function to invoke
*/
Callback(std::shared_ptr<AsyncContinuation> caller, std::function<CbFnT> cb)
: callerContinuation(std::move(caller)), callback(std::move(cb))
{}
public:
std::shared_ptr<AsyncContinuation> callerContinuation;
std::function<CbFnT> callback;
}; };
} // namespace smo } // namespace smo
+2 -1
View File
@@ -11,6 +11,7 @@
#include <lockSet.h> #include <lockSet.h>
#include <asynchronousContinuation.h> #include <asynchronousContinuation.h>
#include <lockerAndInvokerBase.h> #include <lockerAndInvokerBase.h>
#include <callback.h>
namespace smo { namespace smo {
@@ -21,7 +22,7 @@ class SerializedAsynchronousContinuation
public: public:
SerializedAsynchronousContinuation( SerializedAsynchronousContinuation(
const std::shared_ptr<ComponentThread> &caller, const std::shared_ptr<ComponentThread> &caller,
OriginalCbFnT originalCbFn, Callback<OriginalCbFnT> originalCbFn,
std::vector<std::reference_wrapper<SpinLock>> requiredLocks = {}) std::vector<std::reference_wrapper<SpinLock>> requiredLocks = {})
: PostedAsynchronousContinuation<OriginalCbFnT>(caller, originalCbFn), : PostedAsynchronousContinuation<OriginalCbFnT>(caller, originalCbFn),
requiredLocks(*this, std::move(requiredLocks)) requiredLocks(*this, std::move(requiredLocks))
+3 -2
View File
@@ -8,6 +8,7 @@
#include <preprocessor.h> #include <preprocessor.h>
#include <componentThread.h> #include <componentThread.h>
#include <user/deviceAttachmentSpec.h> #include <user/deviceAttachmentSpec.h>
#include <callback.h>
namespace smo { namespace smo {
namespace sense_api { namespace sense_api {
@@ -44,10 +45,10 @@ typedef int (sal_mlo_finalizeIndFn)(void);
typedef void (sal_mlo_attachDeviceReqFn)( typedef void (sal_mlo_attachDeviceReqFn)(
const std::shared_ptr<device::DeviceAttachmentSpec>& desc, const std::shared_ptr<device::DeviceAttachmentSpec>& desc,
const std::shared_ptr<ComponentThread>& componentThread, const std::shared_ptr<ComponentThread>& componentThread,
sal_mlo_attachDeviceReqCbFn cb); Callback<sal_mlo_attachDeviceReqCbFn> cb);
typedef void (sal_mlo_detachDeviceReqFn)( typedef void (sal_mlo_detachDeviceReqFn)(
const std::shared_ptr<device::DeviceAttachmentSpec>& desc, const std::shared_ptr<device::DeviceAttachmentSpec>& desc,
sal_mlo_detachDeviceReqCbFn cb); Callback<sal_mlo_detachDeviceReqCbFn> cb);
/** /**
* @brief Hooks provided by Salmanoff to senseApi libraries. * @brief Hooks provided by Salmanoff to senseApi libraries.
+120 -65
View File
@@ -9,8 +9,10 @@
#include <opts.h> #include <opts.h>
#include <user/senseApiDesc.h> #include <user/senseApiDesc.h>
#include <user/deviceAttachmentSpec.h> #include <user/deviceAttachmentSpec.h>
#include <callback.h>
#include <livoxProto1/livoxProto1.h> #include <livoxProto1/livoxProto1.h>
#include <livoxProto1/device.h> #include <livoxProto1/device.h>
#include <asynchronousContinuation.h>
namespace smo { namespace smo {
@@ -50,6 +52,105 @@ static LivoxProto1DllState livoxProto1;
// Attached Livox devices // Attached Livox devices
static std::vector<std::shared_ptr<livoxProto1::Device>> g_attachedDevices; static std::vector<std::shared_ptr<livoxProto1::Device>> g_attachedDevices;
// Continuation classes for async operations
class AttachDeviceReq
: public smo::NonPostedAsynchronousContinuation<sal_mlo_attachDeviceReqCbFn>
{
public:
AttachDeviceReq(
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& spec,
smo::Callback<sal_mlo_attachDeviceReqCbFn> cb)
: smo::NonPostedAsynchronousContinuation<sal_mlo_attachDeviceReqCbFn>(
std::move(cb)),
spec(spec)
{}
public:
const std::shared_ptr<smo::device::DeviceAttachmentSpec> spec;
public:
void attachDeviceReq1(
std::shared_ptr<AttachDeviceReq> context,
bool success, std::shared_ptr<livoxProto1::Device> dev)
{
if (!dev)
{
std::cerr << __func__ << ": Failed to create Livox device: "
<< context->spec->deviceSelector << std::endl;
context->callOriginalCb(false, context->spec);
return;
}
g_attachedDevices.push_back(dev);
if (1 || OptionParser::getOptions().verbose)
{
std::cout << __func__ << ": Successfully attached Livox "
"device: " << context->spec->deviceSelector << " (ID: "
<< context->spec->deviceIdentifier << ")\n";
}
context->callOriginalCb(success, context->spec);
}
};
class DetachDeviceReq
: public smo::NonPostedAsynchronousContinuation<sal_mlo_detachDeviceReqCbFn>
{
public:
DetachDeviceReq(
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& spec,
smo::Callback<sal_mlo_detachDeviceReqCbFn> cb)
: smo::NonPostedAsynchronousContinuation<sal_mlo_detachDeviceReqCbFn>(
std::move(cb)),
spec(spec)
{}
public:
const std::shared_ptr<smo::device::DeviceAttachmentSpec> spec;
public:
void detachDeviceReq1(
std::shared_ptr<DetachDeviceReq> context,
bool success)
{
if (!success)
{
std::cerr << __func__ << ": Failed to destroy Livox device: "
<< context->spec->deviceIdentifier << "\n";
context->callOriginalCb(false, context->spec);
return;
}
// Find the device in g_attachedDevices and remove it.
auto eraseIt = std::find_if(
g_attachedDevices.begin(), g_attachedDevices.end(),
[context](const std::shared_ptr<livoxProto1::Device>& dev)
{
const std::string& devId = dev->discoveredDevice.deviceIdentifier;
std::string devIdPrefix = devId.substr(
0, std::min<size_t>(14, devId.size()));
return devIdPrefix == context->spec->deviceSelector.substr(
0, std::min<size_t>(14, context->spec->deviceSelector.size()));
}
);
if (eraseIt == g_attachedDevices.end())
{
std::cerr << __func__ << ": Race condition: device not found "
"in g_attachedDevices for detachment: "
<< context->spec->deviceIdentifier << "\n";
context->callOriginalCb(false, context->spec);
return;
}
g_attachedDevices.erase(eraseIt);
std::cout << __func__ << ": Successfully detached Livox device: "
<< context->spec->deviceIdentifier << "\n";
context->callOriginalCb(success, context->spec);
}
};
// Callback function declarations // Callback function declarations
extern "C" sal_mlo_initializeIndFn livoxGen1_initializeInd; extern "C" sal_mlo_initializeIndFn livoxGen1_initializeInd;
extern "C" sal_mlo_finalizeIndFn livoxGen1_finalizeInd; extern "C" sal_mlo_finalizeIndFn livoxGen1_finalizeInd;
@@ -152,7 +253,7 @@ extern "C" int livoxGen1_finalizeInd(void)
extern "C" void livoxGen1_attachDeviceReq( extern "C" void livoxGen1_attachDeviceReq(
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc, const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc,
const std::shared_ptr<smo::ComponentThread>& componentThread, const std::shared_ptr<smo::ComponentThread>& componentThread,
smo::sense_api::sal_mlo_attachDeviceReqCbFn cb Callback<smo::sense_api::sal_mlo_attachDeviceReqCbFn> cb
) )
{ {
if (!livoxProto1.livoxProto1_getOrCreateDeviceReq) if (!livoxProto1.livoxProto1_getOrCreateDeviceReq)
@@ -170,7 +271,10 @@ extern "C" void livoxGen1_attachDeviceReq(
for (const auto& dev : g_attachedDevices) for (const auto& dev : g_attachedDevices)
{ {
if (dev->discoveredDevice.deviceIdentifier == desc->deviceIdentifier) if (dev->discoveredDevice.deviceIdentifier == desc->deviceIdentifier)
{ return; } {
cb.callbackFn(true, desc);
return;
}
} }
// Parse integer parameters from provider params with defaults // Parse integer parameters from provider params with defaults
@@ -245,39 +349,23 @@ extern "C" void livoxGen1_attachDeviceReq(
} }
} }
auto request = std::make_shared<AttachDeviceReq>(desc, cb);
(*livoxProto1.livoxProto1_getOrCreateDeviceReq)( (*livoxProto1.livoxProto1_getOrCreateDeviceReq)(
desc->deviceSelector, // deviceIdentifier (broadcast code) desc->deviceSelector, // deviceIdentifier (broadcast code)
componentThread, componentThread,
handshakeTimeoutMs, retryDelayMs, handshakeTimeoutMs, retryDelayMs,
smoIp, smoSubnetNbits, smoIp, smoSubnetNbits,
dataPort, cmdPort, imuPort, dataPort, cmdPort, imuPort,
[desc, cb]( {request, std::bind(
bool success, std::shared_ptr<livoxProto1::Device> dev) -> void &AttachDeviceReq::attachDeviceReq1,
{ request.get(), request,
if (!dev) std::placeholders::_1, std::placeholders::_2)});
{
std::cerr << __func__ << ": Failed to create Livox device: "
<< desc->deviceSelector << std::endl;
cb(false, desc);
return;
}
g_attachedDevices.push_back(dev);
if (1 || OptionParser::getOptions().verbose)
{
std::cout << __func__ << ": Successfully attached Livox "
"device: " << desc->deviceSelector << " (ID: "
<< desc->deviceIdentifier << ")\n";
}
cb(success, desc);
}
);
} }
extern "C" void livoxGen1_detachDeviceReq( extern "C" void livoxGen1_detachDeviceReq(
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc, const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc,
smo::sense_api::sal_mlo_detachDeviceReqCbFn cb Callback<smo::sense_api::sal_mlo_detachDeviceReqCbFn> cb
) )
{ {
/** FIXME: /** FIXME:
@@ -307,51 +395,18 @@ extern "C" void livoxGen1_detachDeviceReq(
std::cerr << std::string(__func__) std::cerr << std::string(__func__)
<< ": Device not found for detachment: " << ": Device not found for detachment: "
<< desc->deviceIdentifier << std::endl; << desc->deviceIdentifier << std::endl;
cb(false, desc); cb.callbackFn(false, desc);
return; return;
} }
auto request = std::make_shared<DetachDeviceReq>(desc, cb);
(*livoxProto1.livoxProto1_destroyDeviceReq)( (*livoxProto1.livoxProto1_destroyDeviceReq)(
*it, *it,
[cb, desc](bool success) {request, std::bind(
{ &DetachDeviceReq::detachDeviceReq1,
if (!success) request.get(), request,
{ std::placeholders::_1)});
std::cerr << __func__ << ": Failed to destroy Livox device: "
<< desc->deviceIdentifier << "\n";
cb(false, desc);
return;
}
// Find the device in g_attachedDevices and remove it.
auto eraseIt = std::find_if(
g_attachedDevices.begin(), g_attachedDevices.end(),
[desc](const std::shared_ptr<livoxProto1::Device>& dev)
{
const std::string& devId = dev->discoveredDevice.deviceIdentifier;
std::string devIdPrefix = devId.substr(
0, std::min<size_t>(14, devId.size()));
return devIdPrefix == desc->deviceSelector.substr(
0, std::min<size_t>(14, desc->deviceSelector.size()));
}
);
if (eraseIt == g_attachedDevices.end())
{
std::cerr << __func__ << ": Race condition: device not found "
"in g_attachedDevices for detachment: "
<< desc->deviceIdentifier << "\n";
cb(false, desc);
return;
}
g_attachedDevices.erase(eraseIt);
std::cout << __func__ << ": Successfully detached Livox device: "
<< desc->deviceIdentifier << "\n";
cb(success, desc);
}
);
} }
// Exported function // Exported function
+6 -5
View File
@@ -8,6 +8,7 @@
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <user/senseApiDesc.h> #include <user/senseApiDesc.h>
#include <user/deviceAttachmentSpec.h> #include <user/deviceAttachmentSpec.h>
#include <callback.h>
#include <xcbXorg/xcbXorg.h> #include <xcbXorg/xcbXorg.h>
#include "xcbWindow.h" #include "xcbWindow.h"
@@ -276,7 +277,7 @@ static int xcbWindow_finalizeInd(void)
static void xcbWindow_attachDeviceReq( static void xcbWindow_attachDeviceReq(
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc, const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc,
const std::shared_ptr<smo::ComponentThread>& componentThread, const std::shared_ptr<smo::ComponentThread>& componentThread,
smo::sense_api::sal_mlo_attachDeviceReqCbFn cb smo::Callback<smo::sense_api::sal_mlo_attachDeviceReqCbFn> cb
) )
{ {
// Not used yet, but may be used later. // Not used yet, but may be used later.
@@ -289,12 +290,12 @@ static void xcbWindow_attachDeviceReq(
<< g_attachedWindows.back()->stringify() << g_attachedWindows.back()->stringify()
<< "\n"; << "\n";
cb(true, desc); cb.callbackFn(true, desc);
} }
static void xcbWindow_detachDeviceReq( static void xcbWindow_detachDeviceReq(
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& spec, const std::shared_ptr<smo::device::DeviceAttachmentSpec>& spec,
smo::sense_api::sal_mlo_detachDeviceReqCbFn cb smo::Callback<smo::sense_api::sal_mlo_detachDeviceReqCbFn> cb
) )
{ {
auto it = std::find_if(g_attachedWindows.begin(), g_attachedWindows.end(), auto it = std::find_if(g_attachedWindows.begin(), g_attachedWindows.end(),
@@ -308,7 +309,7 @@ static void xcbWindow_detachDeviceReq(
std::cerr << __func__ << ": Device not found for detachment:\n" std::cerr << __func__ << ": Device not found for detachment:\n"
<< spec->stringify() << "\n"; << spec->stringify() << "\n";
cb(false, spec); cb.callbackFn(false, spec);
return; return;
} }
@@ -316,7 +317,7 @@ static void xcbWindow_detachDeviceReq(
std::cout << __func__ << ": Detached X11 window device:\n" std::cout << __func__ << ": Detached X11 window device:\n"
<< spec->stringify() << "\n"; << spec->stringify() << "\n";
cb(true, spec); cb.callbackFn(true, spec);
} }
// SenseApi descriptor // SenseApi descriptor
+10 -9
View File
@@ -2,6 +2,7 @@
#include <opts.h> #include <opts.h>
#include <asynchronousContinuation.h> #include <asynchronousContinuation.h>
#include <asynchronousLoop.h> #include <asynchronousLoop.h>
#include <callback.h>
#include <body/body.h> #include <body/body.h>
#include <componentThread.h> #include <componentThread.h>
#include <mind.h> #include <mind.h>
@@ -21,7 +22,7 @@ class Body::InitializeReq
public: public:
InitializeReq( InitializeReq(
Mind &parent, const std::shared_ptr<ComponentThread> &caller, Mind &parent, const std::shared_ptr<ComponentThread> &caller,
bodyLifetimeMgmtOpCbFn callback) Callback<bodyLifetimeMgmtOpCbFn> callback)
: PostedAsynchronousContinuation<bodyLifetimeMgmtOpCbFn>(caller, callback), : PostedAsynchronousContinuation<bodyLifetimeMgmtOpCbFn>(caller, callback),
parent(parent) parent(parent)
{} {}
@@ -78,10 +79,10 @@ public:
} }
sense_api::SenseApiManager::getInstance() sense_api::SenseApiManager::getInstance()
.attachAllSenseDevicesFromSpecsReq( .attachAllSenseDevicesFromSpecsReq(
std::bind( {context, std::bind(
&InitializeReq::initializeReq2, &InitializeReq::initializeReq2,
context.get(), context, context.get(), context,
std::placeholders::_1)); std::placeholders::_1)});
} }
void initializeReq2( void initializeReq2(
@@ -117,10 +118,10 @@ 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( sense_api::SenseApiManager::getInstance().detachAllSenseDevicesReq(
std::bind( {context, std::bind(
&FinalizeReq::finalizeReq2, &FinalizeReq::finalizeReq2,
context.get(), context, context.get(), context,
std::placeholders::_1)); std::placeholders::_1)});
} }
void finalizeReq2( void finalizeReq2(
@@ -141,7 +142,7 @@ public:
} }
}; };
void Body::initializeReq(bodyLifetimeMgmtOpCbFn callback) void Body::initializeReq(Callback<bodyLifetimeMgmtOpCbFn> callback)
{ {
auto mrntt = ComponentThread::getSelf(); auto mrntt = ComponentThread::getSelf();
@@ -160,7 +161,7 @@ void Body::initializeReq(bodyLifetimeMgmtOpCbFn callback)
request.get(), request)); request.get(), request));
} }
void Body::finalizeReq(bodyLifetimeMgmtOpCbFn callback) void Body::finalizeReq(Callback<bodyLifetimeMgmtOpCbFn> callback)
{ {
auto mrntt = ComponentThread::getSelf(); auto mrntt = ComponentThread::getSelf();
@@ -168,7 +169,7 @@ void Body::finalizeReq(bodyLifetimeMgmtOpCbFn callback)
{ {
std::cerr << __func__ << ": Must be invoked by Mrntt thread" std::cerr << __func__ << ": Must be invoked by Mrntt thread"
<< std::endl; << std::endl;
callback(false); callback.callbackFn(false);
return; return;
} }
@@ -176,7 +177,7 @@ void Body::finalizeReq(bodyLifetimeMgmtOpCbFn callback)
{ {
std::cout << "Mrntt: Body component not initialized. " std::cout << "Mrntt: Body component not initialized. "
<< "Skipping finalization." << "\n"; << "Skipping finalization." << "\n";
callback(true); callback.callbackFn(true);
return; return;
} }
+9 -8
View File
@@ -5,6 +5,7 @@
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <opts.h> #include <opts.h>
#include <asynchronousContinuation.h> #include <asynchronousContinuation.h>
#include <callback.h>
#include <mind.h> #include <mind.h>
#include <mindManager/mindManager.h> #include <mindManager/mindManager.h>
#include <componentThread.h> #include <componentThread.h>
@@ -96,8 +97,8 @@ void MindThread::main(MindThread& self)
if (sendExceptionInd) if (sendExceptionInd)
{ {
mrntt::mrntt.finalizeReq( mrntt::mrntt.finalizeReq(
std::bind( {nullptr, std::bind(
&mrntt::marionetteFinalizeReqCb, std::placeholders::_1)); &mrntt::marionetteFinalizeReqCb, std::placeholders::_1)});
} }
} }
@@ -111,7 +112,7 @@ public:
ThreadLifetimeMgmtOp( ThreadLifetimeMgmtOp(
const std::shared_ptr<ComponentThread> &caller, const std::shared_ptr<ComponentThread> &caller,
const std::shared_ptr<MindThread> &target, const std::shared_ptr<MindThread> &target,
threadLifetimeMgmtOpCbFn callback) Callback<threadLifetimeMgmtOpCbFn> callback)
: PostedAsynchronousContinuation<threadLifetimeMgmtOpCbFn>( : PostedAsynchronousContinuation<threadLifetimeMgmtOpCbFn>(
caller, callback), caller, callback),
target(target) target(target)
@@ -205,7 +206,7 @@ void ComponentThread::cleanup(void)
this->keepLooping = false; this->keepLooping = false;
} }
void MindThread::joltThreadReq(threadLifetimeMgmtOpCbFn callback) void MindThread::joltThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback)
{ {
/** EXPLANATION: /** EXPLANATION:
* We can't use shared_from_this() here because JOLTing occurs prior to * We can't use shared_from_this() here because JOLTing occurs prior to
@@ -241,7 +242,7 @@ void MindThread::joltThreadReq(threadLifetimeMgmtOpCbFn callback)
} }
// Thread management method implementations // Thread management method implementations
void MindThread::startThreadReq(threadLifetimeMgmtOpCbFn callback) void MindThread::startThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback)
{ {
std::shared_ptr<ComponentThread> caller = getSelf(); std::shared_ptr<ComponentThread> caller = getSelf();
auto request = std::make_shared<ThreadLifetimeMgmtOp>( auto request = std::make_shared<ThreadLifetimeMgmtOp>(
@@ -253,7 +254,7 @@ void MindThread::startThreadReq(threadLifetimeMgmtOpCbFn callback)
request.get(), request)); request.get(), request));
} }
void MindThread::exitThreadReq(threadLifetimeMgmtOpCbFn callback) void MindThread::exitThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback)
{ {
std::shared_ptr<ComponentThread> caller = getSelf(); std::shared_ptr<ComponentThread> caller = getSelf();
auto request = std::make_shared<ThreadLifetimeMgmtOp>( auto request = std::make_shared<ThreadLifetimeMgmtOp>(
@@ -270,7 +271,7 @@ void MindThread::exitThreadReq(threadLifetimeMgmtOpCbFn callback)
request.get(), request)); request.get(), request));
} }
void MindThread::pauseThreadReq(threadLifetimeMgmtOpCbFn callback) void MindThread::pauseThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback)
{ {
if (id == ComponentThread::MRNTT) if (id == ComponentThread::MRNTT)
{ {
@@ -288,7 +289,7 @@ void MindThread::pauseThreadReq(threadLifetimeMgmtOpCbFn callback)
request.get(), request)); request.get(), request));
} }
void MindThread::resumeThreadReq(threadLifetimeMgmtOpCbFn callback) void MindThread::resumeThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback)
{ {
if (id == ComponentThread::MRNTT) if (id == ComponentThread::MRNTT)
{ {
+6 -5
View File
@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include <opts.h> #include <opts.h>
#include <asynchronousContinuation.h> #include <asynchronousContinuation.h>
#include <callback.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>
@@ -45,7 +46,7 @@ public:
NewDeviceAttachmentSpecInd( NewDeviceAttachmentSpecInd(
std::shared_ptr<DeviceAttachmentSpec> s, std::shared_ptr<DeviceAttachmentSpec> s,
const std::shared_ptr<ComponentThread> &caller, const std::shared_ptr<ComponentThread> &caller,
newDeviceAttachmentSpecIndCbFn cb) Callback<newDeviceAttachmentSpecIndCbFn> cb)
: PostedAsynchronousContinuation<newDeviceAttachmentSpecIndCbFn>( : PostedAsynchronousContinuation<newDeviceAttachmentSpecIndCbFn>(
caller, cb), caller, cb),
spec(s) spec(s)
@@ -61,10 +62,10 @@ public:
{ {
sense_api::SenseApiManager::getInstance().attachSenseDeviceReq( sense_api::SenseApiManager::getInstance().attachSenseDeviceReq(
spec, spec,
std::bind( {context, std::bind(
&NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd2, &NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd2,
context.get(), context, context.get(), context,
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2)});
} }
void newDeviceAttachmentSpecInd2( void newDeviceAttachmentSpecInd2(
@@ -125,14 +126,14 @@ public:
void DeviceManager::newDeviceAttachmentSpecInd( void DeviceManager::newDeviceAttachmentSpecInd(
std::shared_ptr<DeviceAttachmentSpec> spec, std::shared_ptr<DeviceAttachmentSpec> spec,
newDeviceAttachmentSpecIndCbFn callback) Callback<newDeviceAttachmentSpecIndCbFn> callback)
{ {
// Check if a DeviceAttachmentSpec already matches // Check if a DeviceAttachmentSpec already matches
for (const auto& existingSpec : deviceAttachmentSpecs) for (const auto& existingSpec : deviceAttachmentSpecs)
{ {
if (!(*existingSpec == *spec)) { continue; } if (!(*existingSpec == *spec)) { continue; }
// Already exists, callback with error // Already exists, callback with error
callback(false, nullptr, spec); callback.callbackFn(false, nullptr, spec);
return; return;
} }
+3 -2
View File
@@ -3,6 +3,7 @@
#include <component.h> #include <component.h>
#include <functional> #include <functional>
#include <callback.h>
namespace smo { namespace smo {
@@ -19,8 +20,8 @@ public:
~Body() = default; ~Body() = default;
typedef std::function<void(bool)> bodyLifetimeMgmtOpCbFn; typedef std::function<void(bool)> bodyLifetimeMgmtOpCbFn;
void initializeReq(bodyLifetimeMgmtOpCbFn callback); void initializeReq(Callback<bodyLifetimeMgmtOpCbFn> callback);
void finalizeReq(bodyLifetimeMgmtOpCbFn callback); void finalizeReq(Callback<bodyLifetimeMgmtOpCbFn> callback);
private: private:
class InitializeReq; class InitializeReq;
+3 -2
View File
@@ -4,6 +4,7 @@
#include <config.h> #include <config.h>
#include <memory> #include <memory>
#include <functional> #include <functional>
#include <callback.h>
namespace smo { namespace smo {
@@ -44,8 +45,8 @@ public:
public: public:
typedef std::function<void(bool)> mrnttLifetimeMgmtOpCbFn; typedef std::function<void(bool)> mrnttLifetimeMgmtOpCbFn;
void initializeReq(mrnttLifetimeMgmtOpCbFn callback); void initializeReq(Callback<mrnttLifetimeMgmtOpCbFn> callback);
void finalizeReq(mrnttLifetimeMgmtOpCbFn callback); void finalizeReq(Callback<mrnttLifetimeMgmtOpCbFn> callback);
private: private:
class MrnttLifetimeMgmtOp; class MrnttLifetimeMgmtOp;
+6 -5
View File
@@ -12,6 +12,7 @@
#include <sched.h> #include <sched.h>
#include <unistd.h> #include <unistd.h>
#include <memory> #include <memory>
#include <callback.h>
namespace smo { namespace smo {
@@ -137,10 +138,10 @@ public:
// Thread management methods // Thread management methods
typedef std::function<void()> threadLifetimeMgmtOpCbFn; typedef std::function<void()> threadLifetimeMgmtOpCbFn;
void startThreadReq(threadLifetimeMgmtOpCbFn callback); void startThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback);
void exitThreadReq(threadLifetimeMgmtOpCbFn callback); void exitThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback);
void pauseThreadReq(threadLifetimeMgmtOpCbFn callback); void pauseThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback);
void resumeThreadReq(threadLifetimeMgmtOpCbFn callback); void resumeThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback);
/** /**
* JOLTs this thread to begin processing after global initialization. * JOLTs this thread to begin processing after global initialization.
@@ -149,7 +150,7 @@ public:
* event loops and set up TLS vars after all global constructors have * event loops and set up TLS vars after all global constructors have
* completed. This prevents race conditions during system startup. * completed. This prevents race conditions during system startup.
*/ */
void joltThreadReq(threadLifetimeMgmtOpCbFn callback); void joltThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback);
// CPU management methods // CPU management methods
void pinToCpu(int cpuId); void pinToCpu(int cpuId);
@@ -10,6 +10,7 @@
#include <functional> #include <functional>
#include <user/deviceAttachmentSpec.h> #include <user/deviceAttachmentSpec.h>
#include <deviceManager/device.h> #include <deviceManager/device.h>
#include <callback.h>
namespace smo { namespace smo {
namespace device { namespace device {
@@ -41,7 +42,7 @@ public:
newDeviceAttachmentSpecIndCbFn; newDeviceAttachmentSpecIndCbFn;
void newDeviceAttachmentSpecInd( void newDeviceAttachmentSpecInd(
std::shared_ptr<DeviceAttachmentSpec> spec, std::shared_ptr<DeviceAttachmentSpec> spec,
newDeviceAttachmentSpecIndCbFn callback); Callback<newDeviceAttachmentSpecIndCbFn> callback);
private: private:
DeviceManager() = default; DeviceManager() = default;
+11 -7
View File
@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
#include <string> #include <string>
#include <callback.h>
#include <component.h> #include <component.h>
#include <componentThread.h> #include <componentThread.h>
@@ -23,8 +24,8 @@ public:
~Mind(void) = default; ~Mind(void) = default;
typedef std::function<void(bool)> mindLifetimeMgmtOpCbFn; typedef std::function<void(bool)> mindLifetimeMgmtOpCbFn;
void initializeReq(mindLifetimeMgmtOpCbFn callback); void initializeReq(Callback<mindLifetimeMgmtOpCbFn> callback);
void finalizeReq(mindLifetimeMgmtOpCbFn callback); void finalizeReq(Callback<mindLifetimeMgmtOpCbFn> callback);
// ComponentThread access methods // ComponentThread access methods
std::shared_ptr<MindThread> getComponentThread( std::shared_ptr<MindThread> getComponentThread(
@@ -36,11 +37,14 @@ public:
// Thread management methods (moved from ComponentThread) // Thread management methods (moved from ComponentThread)
typedef std::function<void()> mindThreadLifetimeMgmtOpCbFn; typedef std::function<void()> mindThreadLifetimeMgmtOpCbFn;
void joltAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback); void joltAllMindThreadsReq(Callback<mindThreadLifetimeMgmtOpCbFn> callback);
void startAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback); void startAllMindThreadsReq(
void pauseAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback); Callback<mindThreadLifetimeMgmtOpCbFn> callback);
void resumeAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback); void pauseAllMindThreadsReq(
void exitAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback); Callback<mindThreadLifetimeMgmtOpCbFn> callback);
void resumeAllMindThreadsReq(
Callback<mindThreadLifetimeMgmtOpCbFn> callback);
void exitAllMindThreadsReq(Callback<mindThreadLifetimeMgmtOpCbFn> callback);
// CPU distribution method // CPU distribution method
void distributeAndPinThreadsAcrossCpus(); void distributeAndPinThreadsAcrossCpus();
+5 -4
View File
@@ -11,6 +11,7 @@
#include <asynchronousLoop.h> #include <asynchronousLoop.h>
#include <senseApis/senseApiLib.h> #include <senseApis/senseApiLib.h>
#include <user/deviceAttachmentSpec.h> #include <user/deviceAttachmentSpec.h>
#include <callback.h>
namespace smo { namespace smo {
namespace sense_api { namespace sense_api {
@@ -54,10 +55,10 @@ public:
void attachSenseDeviceReq( void attachSenseDeviceReq(
const std::shared_ptr<device::DeviceAttachmentSpec>& spec, const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
attachSenseDeviceReqCbFn cb); Callback<attachSenseDeviceReqCbFn> cb);
void detachSenseDeviceReq( void detachSenseDeviceReq(
const std::shared_ptr<device::DeviceAttachmentSpec>& spec, const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
detachSenseDeviceReqCbFn cb); Callback<detachSenseDeviceReqCbFn> cb);
typedef std::function<void(AsynchronousLoop &results)> typedef std::function<void(AsynchronousLoop &results)>
attachAllSenseDevicesFromSpecsReqCbFn; attachAllSenseDevicesFromSpecsReqCbFn;
@@ -65,9 +66,9 @@ public:
detachAllSenseDevicesReqCbFn; detachAllSenseDevicesReqCbFn;
void attachAllSenseDevicesFromSpecsReq( void attachAllSenseDevicesFromSpecsReq(
attachAllSenseDevicesFromSpecsReqCbFn cb); Callback<attachAllSenseDevicesFromSpecsReqCbFn> cb);
void detachAllSenseDevicesReq( void detachAllSenseDevicesReq(
detachAllSenseDevicesReqCbFn cb); Callback<detachAllSenseDevicesReqCbFn> cb);
std::string stringifyLibs() const; std::string stringifyLibs() const;
+12 -11
View File
@@ -1,6 +1,7 @@
#include <iostream> #include <iostream>
#include <asynchronousContinuation.h> #include <asynchronousContinuation.h>
#include <asynchronousLoop.h> #include <asynchronousLoop.h>
#include <callback.h>
#include <component.h> #include <component.h>
#include <componentThread.h> #include <componentThread.h>
#include <mindManager/mindManager.h> #include <mindManager/mindManager.h>
@@ -15,7 +16,7 @@ class MarionetteComponent::MrnttLifetimeMgmtOp
public: public:
MrnttLifetimeMgmtOp( MrnttLifetimeMgmtOp(
MarionetteComponent &parent, const std::shared_ptr<ComponentThread> &caller, MarionetteComponent &parent, const std::shared_ptr<ComponentThread> &caller,
mrnttLifetimeMgmtOpCbFn callback) Callback<mrnttLifetimeMgmtOpCbFn> callback)
: PostedAsynchronousContinuation<mrnttLifetimeMgmtOpCbFn>( : PostedAsynchronousContinuation<mrnttLifetimeMgmtOpCbFn>(
caller, callback), caller, callback),
parent(parent) parent(parent)
@@ -37,10 +38,9 @@ public:
} }
smo::mind::globalMind = std::make_shared<Mind>(); smo::mind::globalMind = std::make_shared<Mind>();
smo::mind::globalMind->initializeReq( smo::mind::globalMind->initializeReq({context, std::bind(
std::bind( &MrnttLifetimeMgmtOp::initializeReq2,
&MrnttLifetimeMgmtOp::initializeReq2, this, context, std::placeholders::_1)});
this, context, std::placeholders::_1));
} }
void initializeReq2( void initializeReq2(
@@ -70,10 +70,9 @@ public:
+ ": Must be executed on Marionette thread"); + ": Must be executed on Marionette thread");
} }
smo::mind::globalMind->finalizeReq( smo::mind::globalMind->finalizeReq({context, std::bind(
std::bind( &MrnttLifetimeMgmtOp::finalizeReq2,
&MrnttLifetimeMgmtOp::finalizeReq2, this, context, std::placeholders::_1)});
this, context, std::placeholders::_1));
} }
void finalizeReq2( void finalizeReq2(
@@ -93,7 +92,8 @@ public:
} }
}; };
void MarionetteComponent::initializeReq(mrnttLifetimeMgmtOpCbFn callback) void MarionetteComponent::initializeReq(
Callback<mrnttLifetimeMgmtOpCbFn> callback)
{ {
auto mrntt = ComponentThread::getSelf(); auto mrntt = ComponentThread::getSelf();
@@ -112,7 +112,8 @@ void MarionetteComponent::initializeReq(mrnttLifetimeMgmtOpCbFn callback)
request.get(), request)); request.get(), request));
} }
void MarionetteComponent::finalizeReq(mrnttLifetimeMgmtOpCbFn callback) void MarionetteComponent::finalizeReq(
Callback<mrnttLifetimeMgmtOpCbFn> callback)
{ {
auto mrntt = ComponentThread::getSelf(); auto mrntt = ComponentThread::getSelf();
+11 -15
View File
@@ -56,10 +56,9 @@ void marionetteInitializeReqCb(bool success)
std::cerr << __func__ << ": Failed to initialize Marionette. Shutting down." std::cerr << __func__ << ": Failed to initialize Marionette. Shutting down."
<< '\n'; << '\n';
mrntt::mrntt.finalizeReq( mrntt::mrntt.finalizeReq({nullptr, std::bind(
std::bind( &mrntt::marionetteFinalizeReqCb,
&mrntt::marionetteFinalizeReqCb, std::placeholders::_1)});
std::placeholders::_1));
} }
} // namespace mrntt } // namespace mrntt
@@ -92,10 +91,9 @@ void MarionetteThread::main(MarionetteThread& self)
default: default:
break; break;
} }
mrntt::mrntt.finalizeReq( mrntt::mrntt.finalizeReq({nullptr, std::bind(
std::bind( &mrntt::marionetteFinalizeReqCb,
&mrntt::marionetteFinalizeReqCb, std::placeholders::_1)});
std::placeholders::_1));
} }
); );
@@ -137,9 +135,8 @@ void MarionetteThread::main(MarionetteThread& self)
callShutdownSalmanoff = true; callShutdownSalmanoff = true;
// Create new Mind instance just before initializeReq // Create new Mind instance just before initializeReq
mrntt::mrntt.initializeReq( mrntt::mrntt.initializeReq({nullptr, std::bind(
std::bind( &mrntt::marionetteInitializeReqCb, std::placeholders::_1)});
&mrntt::marionetteInitializeReqCb, std::placeholders::_1));
std::cout << __func__ << ": Entering event loop" << "\n"; std::cout << __func__ << ": Entering event loop" << "\n";
@@ -183,10 +180,9 @@ void MarionetteThread::main(MarionetteThread& self)
if (sendExceptionInd) if (sendExceptionInd)
{ {
mrntt::exitCode = EXIT_FAILURE; mrntt::exitCode = EXIT_FAILURE;
mrntt::mrntt.finalizeReq( mrntt::mrntt.finalizeReq({nullptr, std::bind(
std::bind( &mrntt::marionetteFinalizeReqCb,
&mrntt::marionetteFinalizeReqCb, std::placeholders::_1)});
std::placeholders::_1));
} }
} }
+53 -42
View File
@@ -2,6 +2,7 @@
#include <opts.h> #include <opts.h>
#include <asynchronousContinuation.h> #include <asynchronousContinuation.h>
#include <asynchronousLoop.h> #include <asynchronousLoop.h>
#include <callback.h>
#include <mind.h> #include <mind.h>
#include <componentThread.h> #include <componentThread.h>
#include <director/director.h> #include <director/director.h>
@@ -89,7 +90,7 @@ class Mind::MindLifetimeMgmtOp
public: public:
MindLifetimeMgmtOp( MindLifetimeMgmtOp(
Mind &parent, const std::shared_ptr<ComponentThread> &caller, Mind &parent, const std::shared_ptr<ComponentThread> &caller,
mindLifetimeMgmtOpCbFn callback) Callback<mindLifetimeMgmtOpCbFn> callback)
: PostedAsynchronousContinuation<mindLifetimeMgmtOpCbFn>( : PostedAsynchronousContinuation<mindLifetimeMgmtOpCbFn>(
caller, callback), caller, callback),
parent(parent) parent(parent)
@@ -105,9 +106,9 @@ public:
{ {
/* Jolt the threads, then start them */ /* Jolt the threads, then start them */
parent.joltAllMindThreadsReq( parent.joltAllMindThreadsReq(
std::bind( {context, std::bind(
&MindLifetimeMgmtOp::initializeReq2, &MindLifetimeMgmtOp::initializeReq2,
context.get(), context)); context.get(), context)});
} }
void initializeReq2( void initializeReq2(
@@ -117,9 +118,9 @@ public:
std::cout << "Mrntt: All mind threads JOLTed." << "\n"; std::cout << "Mrntt: All mind threads JOLTed." << "\n";
parent.startAllMindThreadsReq( parent.startAllMindThreadsReq(
std::bind( {context, std::bind(
&MindLifetimeMgmtOp::initializeReq3, &MindLifetimeMgmtOp::initializeReq3,
context.get(), context)); context.get(), context)});
} }
void initializeReq3( void initializeReq3(
@@ -129,9 +130,9 @@ public:
std::cout << "Mrntt: All mind threads started." << "\n"; std::cout << "Mrntt: All mind threads started." << "\n";
parent.body.initializeReq( parent.body.initializeReq(
std::bind( {context, std::bind(
&MindLifetimeMgmtOp::initializeReq4, &MindLifetimeMgmtOp::initializeReq4,
context.get(), context, std::placeholders::_1)); context.get(), context, std::placeholders::_1)});
} }
void initializeReq4( void initializeReq4(
@@ -148,9 +149,9 @@ public:
) )
{ {
parent.body.finalizeReq( parent.body.finalizeReq(
std::bind( {context, std::bind(
&MindLifetimeMgmtOp::finalizeReq2, &MindLifetimeMgmtOp::finalizeReq2,
context.get(), context, std::placeholders::_1)); context.get(), context, std::placeholders::_1)});
} }
void finalizeReq2( void finalizeReq2(
@@ -169,9 +170,9 @@ public:
* messages from mrntt after processing the exit request. * messages from mrntt after processing the exit request.
*/ */
parent.joltAllMindThreadsReq( parent.joltAllMindThreadsReq(
std::bind( {context, std::bind(
&MindLifetimeMgmtOp::finalizeReq3, &MindLifetimeMgmtOp::finalizeReq3,
context.get(), context)); context.get(), context)});
} }
void finalizeReq3( void finalizeReq3(
@@ -181,9 +182,9 @@ public:
std::cout << "Mrntt: All mind threads JOLTed for finalization." << "\n"; std::cout << "Mrntt: All mind threads JOLTed for finalization." << "\n";
parent.exitAllMindThreadsReq( parent.exitAllMindThreadsReq(
std::bind( {context, std::bind(
&MindLifetimeMgmtOp::finalizeReq4, &MindLifetimeMgmtOp::finalizeReq4,
context.get(), context)); context.get(), context)});
} }
void finalizeReq4( void finalizeReq4(
@@ -195,7 +196,7 @@ public:
} }
}; };
void Mind::initializeReq(mindLifetimeMgmtOpCbFn callback) void Mind::initializeReq(Callback<mindLifetimeMgmtOpCbFn> callback)
{ {
/* Distribute threads across available CPUs */ /* Distribute threads across available CPUs */
try try
@@ -219,7 +220,7 @@ void Mind::initializeReq(mindLifetimeMgmtOpCbFn callback)
request.get(), request)); request.get(), request));
} }
void Mind::finalizeReq(mindLifetimeMgmtOpCbFn callback) void Mind::finalizeReq(Callback<mindLifetimeMgmtOpCbFn> callback)
{ {
const auto& caller = ComponentThread::getSelf(); const auto& caller = ComponentThread::getSelf();
auto request = std::make_shared<MindLifetimeMgmtOp>( auto request = std::make_shared<MindLifetimeMgmtOp>(
@@ -258,7 +259,7 @@ class Mind::MindThreadLifetimeMgmtOp
public: public:
MindThreadLifetimeMgmtOp( MindThreadLifetimeMgmtOp(
Mind &parent,unsigned int nThreads, Mind &parent,unsigned int nThreads,
mindThreadLifetimeMgmtOpCbFn callback) Callback<mindThreadLifetimeMgmtOpCbFn> callback)
: NonPostedAsynchronousContinuation<mindThreadLifetimeMgmtOpCbFn>(callback), : NonPostedAsynchronousContinuation<mindThreadLifetimeMgmtOpCbFn>(callback),
loop(nThreads), loop(nThreads),
parent(parent) parent(parent)
@@ -311,21 +312,23 @@ public:
} }
}; };
void Mind::joltAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback) void Mind::joltAllMindThreadsReq(
Callback<mindThreadLifetimeMgmtOpCbFn> callback
)
{ {
if (threadsHaveBeenJolted) if (threadsHaveBeenJolted)
{ {
std::cout << "Mrntt: All mind threads already JOLTed. " std::cout << "Mrntt: All mind threads already JOLTed. "
<< "Skipping JOLT request." << "\n"; << "Skipping JOLT request." << "\n";
callback(); callback.callbackFn();
return; return;
} }
// If no threads, set flag and call callback immediately // If no threads, set flag and call callback immediately
if (componentThreads.size() == 0 && callback) if (componentThreads.size() == 0 && callback.callbackFn)
{ {
threadsHaveBeenJolted = true; threadsHaveBeenJolted = true;
callback(); callback.callbackFn();
return; return;
} }
@@ -336,19 +339,21 @@ void Mind::joltAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback)
for (auto& thread : componentThreads) for (auto& thread : componentThreads)
{ {
thread->joltThreadReq( thread->joltThreadReq(
std::bind( {request, std::bind(
&MindThreadLifetimeMgmtOp::joltAllMindThreadsReq1, &MindThreadLifetimeMgmtOp::joltAllMindThreadsReq1,
request.get(), request)); request.get(), request)});
} }
} }
// Thread management methods (moved from ComponentThread) // Thread management methods (moved from ComponentThread)
void Mind::startAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback) void Mind::startAllMindThreadsReq(
Callback<mindThreadLifetimeMgmtOpCbFn> callback
)
{ {
// If no threads, call callback immediately // If no threads, call callback immediately
if (componentThreads.size() == 0 && callback) if (componentThreads.size() == 0 && callback.callbackFn)
{ {
callback(); callback.callbackFn();
return; return;
} }
@@ -359,18 +364,20 @@ void Mind::startAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback)
for (auto& thread : componentThreads) for (auto& thread : componentThreads)
{ {
thread->startThreadReq( thread->startThreadReq(
std::bind( {request, std::bind(
&MindThreadLifetimeMgmtOp::executeGenericOpOnAllMindThreadsReq1, &MindThreadLifetimeMgmtOp::executeGenericOpOnAllMindThreadsReq1,
request.get(), request)); request.get(), request)});
} }
} }
void Mind::pauseAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback) void Mind::pauseAllMindThreadsReq(
Callback<mindThreadLifetimeMgmtOpCbFn> callback
)
{ {
// If no threads, call callback immediately // If no threads, call callback immediately
if (componentThreads.size() == 0 && callback) if (componentThreads.size() == 0 && callback.callbackFn)
{ {
callback(); callback.callbackFn();
return; return;
} }
@@ -381,18 +388,20 @@ void Mind::pauseAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback)
for (auto& thread : componentThreads) for (auto& thread : componentThreads)
{ {
thread->pauseThreadReq( thread->pauseThreadReq(
std::bind( {request, std::bind(
&MindThreadLifetimeMgmtOp::executeGenericOpOnAllMindThreadsReq1, &MindThreadLifetimeMgmtOp::executeGenericOpOnAllMindThreadsReq1,
request.get(), request)); request.get(), request)});
} }
} }
void Mind::resumeAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback) void Mind::resumeAllMindThreadsReq(
Callback<mindThreadLifetimeMgmtOpCbFn> callback
)
{ {
// If no threads, call callback immediately // If no threads, call callback immediately
if (componentThreads.size() == 0 && callback) if (componentThreads.size() == 0 && callback.callbackFn)
{ {
callback(); callback.callbackFn();
return; return;
} }
@@ -403,18 +412,20 @@ void Mind::resumeAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback)
for (auto& thread : componentThreads) for (auto& thread : componentThreads)
{ {
thread->resumeThreadReq( thread->resumeThreadReq(
std::bind( {request, std::bind(
&MindThreadLifetimeMgmtOp::executeGenericOpOnAllMindThreadsReq1, &MindThreadLifetimeMgmtOp::executeGenericOpOnAllMindThreadsReq1,
request.get(), request)); request.get(), request)});
} }
} }
void Mind::exitAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback) void Mind::exitAllMindThreadsReq(
Callback<mindThreadLifetimeMgmtOpCbFn> callback
)
{ {
// If no threads, call callback immediately // If no threads, call callback immediately
if (componentThreads.size() == 0 && callback) if (componentThreads.size() == 0 && callback.callbackFn)
{ {
callback(); callback.callbackFn();
return; return;
} }
@@ -425,9 +436,9 @@ void Mind::exitAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback)
for (auto& thread : componentThreads) for (auto& thread : componentThreads)
{ {
thread->exitThreadReq( thread->exitThreadReq(
std::bind( {request, std::bind(
&MindThreadLifetimeMgmtOp::executeGenericOpOnAllMindThreadsReq1, &MindThreadLifetimeMgmtOp::executeGenericOpOnAllMindThreadsReq1,
request.get(), request)); request.get(), request)});
} }
} }
+17 -16
View File
@@ -8,6 +8,7 @@
#include <asynchronousBridge.h> #include <asynchronousBridge.h>
#include <asynchronousContinuation.h> #include <asynchronousContinuation.h>
#include <asynchronousLoop.h> #include <asynchronousLoop.h>
#include <callback.h>
#include <user/senseApiDesc.h> #include <user/senseApiDesc.h>
#include <mind.h> #include <mind.h>
#include <deviceManager/deviceManager.h> #include <deviceManager/deviceManager.h>
@@ -268,7 +269,7 @@ public:
AttachSenseDeviceReq( AttachSenseDeviceReq(
const std::shared_ptr<device::DeviceAttachmentSpec>& spec, const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
const std::shared_ptr<ComponentThread> &caller, const std::shared_ptr<ComponentThread> &caller,
attachSenseDeviceReqCbFn cb) Callback<attachSenseDeviceReqCbFn> cb)
: PostedAsynchronousContinuation<attachSenseDeviceReqCbFn>( : PostedAsynchronousContinuation<attachSenseDeviceReqCbFn>(
caller, cb), caller, cb),
spec(spec) spec(spec)
@@ -335,10 +336,10 @@ public:
lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq( lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq(
spec, threadForAttachment, spec, threadForAttachment,
std::bind( {context, std::bind(
&AttachSenseDeviceReq::attachSenseDeviceReq2, &AttachSenseDeviceReq::attachSenseDeviceReq2,
context.get(), context, context.get(), context,
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2)});
} }
void attachSenseDeviceReq2( void attachSenseDeviceReq2(
@@ -386,10 +387,10 @@ public:
} }
lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq( lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq(
spec, spec,
std::bind( {context, std::bind(
&DetachSenseDeviceReq::detachSenseDeviceReq2, &DetachSenseDeviceReq::detachSenseDeviceReq2,
context.get(), context, context.get(), context,
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2)});
} }
void detachSenseDeviceReq2( void detachSenseDeviceReq2(
@@ -407,7 +408,7 @@ public:
void SenseApiManager::attachSenseDeviceReq( void SenseApiManager::attachSenseDeviceReq(
const std::shared_ptr<device::DeviceAttachmentSpec>& spec, const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
attachSenseDeviceReqCbFn cb Callback<attachSenseDeviceReqCbFn> cb
) )
{ {
const auto& caller = ComponentThread::getSelf(); const auto& caller = ComponentThread::getSelf();
@@ -422,7 +423,7 @@ void SenseApiManager::attachSenseDeviceReq(
void SenseApiManager::detachSenseDeviceReq( void SenseApiManager::detachSenseDeviceReq(
const std::shared_ptr<device::DeviceAttachmentSpec>& spec, const std::shared_ptr<device::DeviceAttachmentSpec>& spec,
detachSenseDeviceReqCbFn cb Callback<detachSenseDeviceReqCbFn> cb
) )
{ {
const auto& caller = ComponentThread::getSelf(); const auto& caller = ComponentThread::getSelf();
@@ -443,7 +444,7 @@ public:
AttachAllSenseDevicesFromSpecsReq( AttachAllSenseDevicesFromSpecsReq(
const unsigned int totalNSpecs, const unsigned int totalNSpecs,
const std::shared_ptr<ComponentThread>& caller, const std::shared_ptr<ComponentThread>& caller,
attachAllSenseDevicesFromSpecsReqCbFn cb) Callback<attachAllSenseDevicesFromSpecsReqCbFn> cb)
: PostedAsynchronousContinuation<attachAllSenseDevicesFromSpecsReqCbFn>( : PostedAsynchronousContinuation<attachAllSenseDevicesFromSpecsReqCbFn>(
caller, cb), caller, cb),
loop(totalNSpecs) loop(totalNSpecs)
@@ -458,10 +459,10 @@ public:
{ {
SenseApiManager::getInstance().attachSenseDeviceReq( SenseApiManager::getInstance().attachSenseDeviceReq(
spec, spec,
std::bind( {context, std::bind(
&AttachAllSenseDevicesFromSpecsReq::attachAllSenseDevicesFromSpecsReq2, &AttachAllSenseDevicesFromSpecsReq::attachAllSenseDevicesFromSpecsReq2,
context.get(), context, context.get(), context,
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2)});
} }
} }
@@ -499,13 +500,13 @@ public:
}; };
void SenseApiManager::attachAllSenseDevicesFromSpecsReq( void SenseApiManager::attachAllSenseDevicesFromSpecsReq(
attachAllSenseDevicesFromSpecsReqCbFn cb Callback<attachAllSenseDevicesFromSpecsReqCbFn> cb
) )
{ {
if (device::DeviceManager::getInstance().deviceAttachmentSpecs.size() == 0) if (device::DeviceManager::getInstance().deviceAttachmentSpecs.size() == 0)
{ {
AsynchronousLoop tmp(0); AsynchronousLoop tmp(0);
cb(tmp); cb.callbackFn(tmp);
return; return;
} }
@@ -534,10 +535,10 @@ public:
{ {
SenseApiManager::getInstance().detachSenseDeviceReq( SenseApiManager::getInstance().detachSenseDeviceReq(
spec, spec,
std::bind( {context, std::bind(
&DetachAllSenseDevicesReq::detachAllSenseDevicesReq2, &DetachAllSenseDevicesReq::detachAllSenseDevicesReq2,
context.get(), context, context.get(), context,
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2)});
} }
} }
@@ -571,13 +572,13 @@ public:
}; };
void SenseApiManager::detachAllSenseDevicesReq( void SenseApiManager::detachAllSenseDevicesReq(
detachAllSenseDevicesReqCbFn cb Callback<detachAllSenseDevicesReqCbFn> cb
) )
{ {
if (device::DeviceManager::getInstance().deviceAttachmentSpecs.size() == 0) if (device::DeviceManager::getInstance().deviceAttachmentSpecs.size() == 0)
{ {
AsynchronousLoop tmp(0); AsynchronousLoop tmp(0);
cb(tmp); cb.callbackFn(tmp);
return; return;
} }