From c539e6e9244172303e66e855ffcbe06df5d0ab84 Mon Sep 17 00:00:00 2001 From: Hayodea Hekol Date: Sun, 24 May 2026 23:08:04 -0400 Subject: [PATCH] Add awaiters for DeviceManager continuations --- smocore/include/cpsBoundary/cpsCallbackAReq.h | 93 ++++++++++ .../include/cpsBoundary/stimBuffDeviceAReq.h | 160 ++++++++++++++++++ 2 files changed, 253 insertions(+) create mode 100644 smocore/include/cpsBoundary/cpsCallbackAReq.h create mode 100644 smocore/include/cpsBoundary/stimBuffDeviceAReq.h diff --git a/smocore/include/cpsBoundary/cpsCallbackAReq.h b/smocore/include/cpsBoundary/cpsCallbackAReq.h new file mode 100644 index 0000000..0c16b95 --- /dev/null +++ b/smocore/include/cpsBoundary/cpsCallbackAReq.h @@ -0,0 +1,93 @@ +#ifndef CPS_CALLBACK_AREQ_H +#define CPS_CALLBACK_AREQ_H + +#include +#include +#include +#include + +#include +#include +#include + +namespace smo { +namespace cpsBoundary { + +/** Eager-start CPS callback → coroutine adapter (mirrors + * PuppetThread::ViralThreadLifetimeMgmtInvoker). + */ +template +class CpsCallbackAReq +{ +public: + struct AsyncState + { + std::atomic settled{false}; + Result result{}; + std::coroutine_handle<> callerSchedHandle; + }; + + CpsCallbackAReq( + boost::asio::io_service &resumeIoService, + StartFn startFn) + : asyncState(std::make_shared()), + resumeIoService(resumeIoService) + { + startFn(sscl::cps::Callback{ + nullptr, + [this](auto &&...args) + { + storeResult(std::forward(args)...); + signalSettledAndResumeCaller(); + }}); + } + + bool await_ready() const noexcept + { + return asyncState->settled.load(std::memory_order_acquire); + } + + bool await_suspend(std::coroutine_handle<> callerSchedHandle) noexcept + { + if (asyncState->settled.load(std::memory_order_acquire)) { + return false; + } + + asyncState->callerSchedHandle = callerSchedHandle; + return true; + } + + Result await_resume() noexcept + { + return asyncState->result; + } + +private: + template + void storeResult(Args &&...args) + { + asyncState->result = Result{std::forward(args)...}; + } + + void signalSettledAndResumeCaller() noexcept + { + asyncState->settled.store(true, std::memory_order_release); + + std::coroutine_handle<> handle = asyncState->callerSchedHandle; + if (!handle) { + return; + } + + boost::asio::post( + resumeIoService, + [handle]() { handle.resume(); }); + } + + std::shared_ptr asyncState; + boost::asio::io_service &resumeIoService; +}; + +} // namespace cpsBoundary +} // namespace smo + +#endif // CPS_CALLBACK_AREQ_H diff --git a/smocore/include/cpsBoundary/stimBuffDeviceAReq.h b/smocore/include/cpsBoundary/stimBuffDeviceAReq.h new file mode 100644 index 0000000..44a2c72 --- /dev/null +++ b/smocore/include/cpsBoundary/stimBuffDeviceAReq.h @@ -0,0 +1,160 @@ +#ifndef STIM_BUFF_DEVICE_AREQ_H +#define STIM_BUFF_DEVICE_AREQ_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace smo { +namespace cpsBoundary { + +struct StimBuffDeviceOpResult +{ + bool success = false; + std::shared_ptr deviceSpec; +}; + +struct AttachStimBuffDeviceAReq +{ + struct AsyncState + { + std::atomic settled{false}; + StimBuffDeviceOpResult result; + std::coroutine_handle<> callerSchedHandle; + }; + + AttachStimBuffDeviceAReq( + const std::shared_ptr &spec, + stim_buff::StimBuffApiLib &lib, + const std::shared_ptr &threadForAttachment, + boost::asio::io_service &resumeIoService) + : asyncState(std::make_shared()), + resumeIoService(resumeIoService) + { + lib.stimBuffApiDesc.sal_mgmt_libOps.attachDeviceReq( + spec, threadForAttachment, + {nullptr, + [asyncState = asyncState, &resumeIoService = resumeIoService]( + bool success, + std::shared_ptr deviceSpec) + { + asyncState->result = StimBuffDeviceOpResult{ + success, deviceSpec}; + + asyncState->settled.store( + true, std::memory_order_release); + + std::coroutine_handle<> handle = + asyncState->callerSchedHandle; + + if (!handle) { + return; + } + + boost::asio::post( + resumeIoService, + [handle]() { handle.resume(); }); + }}); + } + + bool await_ready() const noexcept + { + return asyncState->settled.load(std::memory_order_acquire); + } + + bool await_suspend(std::coroutine_handle<> callerSchedHandle) noexcept + { + if (asyncState->settled.load(std::memory_order_acquire)) { + return false; + } + + asyncState->callerSchedHandle = callerSchedHandle; + return true; + } + + StimBuffDeviceOpResult await_resume() noexcept + { + return asyncState->result; + } + + std::shared_ptr asyncState; + boost::asio::io_service &resumeIoService; +}; + +struct DetachStimBuffDeviceAReq +{ + struct AsyncState + { + std::atomic settled{false}; + StimBuffDeviceOpResult result; + std::coroutine_handle<> callerSchedHandle; + }; + + DetachStimBuffDeviceAReq( + const std::shared_ptr &spec, + stim_buff::StimBuffApiLib &lib, + boost::asio::io_service &resumeIoService) + : asyncState(std::make_shared()), + resumeIoService(resumeIoService) + { + lib.stimBuffApiDesc.sal_mgmt_libOps.detachDeviceReq( + spec, + {nullptr, + [asyncState = asyncState, &resumeIoService = resumeIoService]( + bool success, + std::shared_ptr deviceSpec) + { + asyncState->result = StimBuffDeviceOpResult{ + success, deviceSpec}; + + asyncState->settled.store( + true, std::memory_order_release); + + std::coroutine_handle<> handle = + asyncState->callerSchedHandle; + + if (!handle) { + return; + } + + boost::asio::post( + resumeIoService, + [handle]() { handle.resume(); }); + }}); + } + + bool await_ready() const noexcept + { + return asyncState->settled.load(std::memory_order_acquire); + } + + bool await_suspend(std::coroutine_handle<> callerSchedHandle) noexcept + { + if (asyncState->settled.load(std::memory_order_acquire)) { + return false; + } + + asyncState->callerSchedHandle = callerSchedHandle; + return true; + } + + StimBuffDeviceOpResult await_resume() noexcept + { + return asyncState->result; + } + + std::shared_ptr asyncState; + boost::asio::io_service &resumeIoService; +}; + +} // namespace cpsBoundary +} // namespace smo + +#endif // STIM_BUFF_DEVICE_AREQ_H