mirror of
https://github.com/latentPrion/libspinscale.git
synced 2026-06-23 19:48:32 +00:00
Impl ViralNonPostingInv; fix member coro thisptr;
This commit is contained in:
@@ -439,7 +439,7 @@ struct Group
|
|||||||
* would be impossible.
|
* would be impossible.
|
||||||
*
|
*
|
||||||
* So we should be able to call resume() directly here without
|
* So we should be able to call resume() directly here without
|
||||||
* post()ing to current_io_context().
|
* post()ing to ComponentThread::getSelf()->getIoService().
|
||||||
*
|
*
|
||||||
* EXPLANATION:
|
* EXPLANATION:
|
||||||
* However, in order to ensure that we keep this adapter coro
|
* However, in order to ensure that we keep this adapter coro
|
||||||
|
|||||||
@@ -47,7 +47,10 @@ struct NonViralPostingInvoker
|
|||||||
*/
|
*/
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << std::this_thread::get_id()
|
oss << std::this_thread::get_id()
|
||||||
<< ": Missing completion lambda: non-viral coroutines require a completion lambda.";
|
<< ": Missing completion lambda: non-viral coroutines require a completion lambda."
|
||||||
|
<< " Promise type=" << typeid(*this).name()
|
||||||
|
<< ". This usually means promise construction did not bind the"
|
||||||
|
<< " (exception_ptr&, function<void()>, ...) constructor.";
|
||||||
throw std::runtime_error(oss.str());
|
throw std::runtime_error(oss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,12 +156,12 @@ struct ViralPostingInvoker
|
|||||||
* from get_return_object(). ~NonPostingInvoker destroys the callee frame.
|
* from get_return_object(). ~NonPostingInvoker destroys the callee frame.
|
||||||
*/
|
*/
|
||||||
struct NonViralNonPostingInvoker
|
struct NonViralNonPostingInvoker
|
||||||
: public NonPostingInvoker<NonPostingPromise>
|
: public NonPostingInvoker<NonPostingPromise<void>, void>
|
||||||
{
|
{
|
||||||
struct promise_type
|
struct promise_type
|
||||||
: public NonPostingPromise
|
: public NonPostingPromise<void>
|
||||||
{
|
{
|
||||||
using NonPostingPromise::NonPostingPromise;
|
using NonPostingPromise<void>::NonPostingPromise;
|
||||||
|
|
||||||
NonViralNonPostingInvoker get_return_object()
|
NonViralNonPostingInvoker get_return_object()
|
||||||
{
|
{
|
||||||
@@ -169,7 +172,10 @@ struct NonViralNonPostingInvoker
|
|||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << std::this_thread::get_id()
|
oss << std::this_thread::get_id()
|
||||||
<< ": Missing completion lambda: non-viral coroutines require a completion lambda.";
|
<< ": Missing completion lambda: non-viral coroutines require a completion lambda."
|
||||||
|
<< " Promise type=" << typeid(*this).name()
|
||||||
|
<< ". This usually means promise construction did not bind the"
|
||||||
|
<< " (exception_ptr&, function<void()>, ...) constructor.";
|
||||||
throw std::runtime_error(oss.str());
|
throw std::runtime_error(oss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +186,7 @@ struct NonViralNonPostingInvoker
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using NonPostingInvoker<NonPostingPromise>::NonPostingInvoker;
|
using NonPostingInvoker<NonPostingPromise<void>, void>::NonPostingInvoker;
|
||||||
|
|
||||||
bool await_ready() const noexcept
|
bool await_ready() const noexcept
|
||||||
{ std::terminate(); }
|
{ std::terminate(); }
|
||||||
@@ -192,6 +198,66 @@ struct NonViralNonPostingInvoker
|
|||||||
{ std::terminate(); }
|
{ std::terminate(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Viral awaitable non-posting coroutine: runs eagerly on the caller thread
|
||||||
|
* (initial_suspend is never). Caller resume uses symmetric transfer when the
|
||||||
|
* caller has registered before callee completion; otherwise PostBackStatus
|
||||||
|
* fast-paths await_resume on co_await.
|
||||||
|
*/
|
||||||
|
template <typename T = void>
|
||||||
|
struct ViralNonPostingInvoker
|
||||||
|
: public NonPostingInvoker<NonPostingPromise<T>, T>
|
||||||
|
{
|
||||||
|
struct promise_type
|
||||||
|
: public NonPostingPromise<T>
|
||||||
|
{
|
||||||
|
using NonPostingPromise<T>::NonPostingPromise;
|
||||||
|
|
||||||
|
ViralNonPostingInvoker<T> get_return_object() noexcept
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
||||||
|
std::cout << __func__ << ": " << std::this_thread::get_id()
|
||||||
|
<< " Returning ViralNonPostingInvoker.\n";
|
||||||
|
#endif
|
||||||
|
this->setSelfSchedHandle(
|
||||||
|
std::coroutine_handle<promise_type>::from_promise(*this));
|
||||||
|
|
||||||
|
return ViralNonPostingInvoker<T>(*this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using NonPostingInvoker<NonPostingPromise<T>, T>::NonPostingInvoker;
|
||||||
|
|
||||||
|
bool await_ready() const noexcept
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
template <typename CallerPromise>
|
||||||
|
bool await_suspend(
|
||||||
|
std::coroutine_handle<CallerPromise> callerSchedHandle) noexcept
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
std::is_base_of_v<PromiseChainLink, CallerPromise>,
|
||||||
|
"ViralNonPostingInvoker caller promise must derive from "
|
||||||
|
"PromiseChainLink");
|
||||||
|
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
||||||
|
std::cout << __func__ << ": " << std::this_thread::get_id()
|
||||||
|
<< " Setting callerSchedHandle.\n";
|
||||||
|
#endif
|
||||||
|
const bool suspendCaller =
|
||||||
|
this->setCallerSchedHandle(callerSchedHandle);
|
||||||
|
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
||||||
|
std::cout << __func__ << ": " << std::this_thread::get_id()
|
||||||
|
<< " CallerFlowExecutor returned suspend=" << suspendCaller
|
||||||
|
<< ".\n";
|
||||||
|
#endif
|
||||||
|
return suspendCaller;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto await_resume()
|
||||||
|
{
|
||||||
|
return NonPostingInvoker<NonPostingPromise<T>, T>::await_resume();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace sscl::co
|
} // namespace sscl::co
|
||||||
|
|
||||||
#endif // INVOKERS_H
|
#endif // INVOKERS_H
|
||||||
|
|||||||
@@ -5,13 +5,14 @@
|
|||||||
#include <coroutine>
|
#include <coroutine>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <spinscale/co/nonPostingPromise.h>
|
#include <spinscale/co/nonPostingPromise.h>
|
||||||
|
|
||||||
namespace sscl::co {
|
namespace sscl::co {
|
||||||
|
|
||||||
template <typename PromiseType>
|
template <typename PromiseType, typename T>
|
||||||
class NonPostingInvoker
|
class NonPostingInvoker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -39,15 +40,55 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValues<void> &completedReturnValues() noexcept
|
template <typename CallerPromise>
|
||||||
|
bool setCallerSchedHandle(
|
||||||
|
std::coroutine_handle<CallerPromise> callerSchedHandle) noexcept
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
std::is_base_of_v<PromiseChainLink, CallerPromise>,
|
||||||
|
"NonPostingInvoker caller promise must derive from PromiseChainLink");
|
||||||
|
|
||||||
|
calleePromise.callerSchedHandle = callerSchedHandle;
|
||||||
|
calleePromise.setCallerPromiseChainLink(
|
||||||
|
&callerSchedHandle.promise());
|
||||||
|
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
||||||
|
std::cout << __func__ << ": " << std::this_thread::get_id()
|
||||||
|
<< " Done setting callerSchedHandle; running CallerFlowExecutor.\n";
|
||||||
|
#endif
|
||||||
|
return calleePromise.postBackStatus.getCallerFlowExecutor()();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValues<T> &completedReturnValues() noexcept
|
||||||
{ return calleePromise.returnValues; }
|
{ return calleePromise.returnValues; }
|
||||||
|
|
||||||
const ReturnValues<void> &completedReturnValues() const noexcept
|
const ReturnValues<T> &completedReturnValues() const noexcept
|
||||||
{ return calleePromise.returnValues; }
|
{ return calleePromise.returnValues; }
|
||||||
|
|
||||||
private:
|
auto await_resume()
|
||||||
|
{
|
||||||
|
calleePromise.postBackStatus.reset();
|
||||||
|
|
||||||
|
ReturnValues<T> &returnValues = calleePromise.returnValues;
|
||||||
|
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
||||||
|
std::cout << __func__ << ": " << std::this_thread::get_id()
|
||||||
|
<< " About to check for and rethrow any exception.\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (returnValues.myExceptionPtr) {
|
||||||
|
std::exception_ptr const captured = returnValues.myExceptionPtr;
|
||||||
|
std::rethrow_exception(captured);
|
||||||
|
}
|
||||||
|
if constexpr (!std::is_void_v<T>)
|
||||||
|
{
|
||||||
|
T result = std::move(returnValues.myReturnValue);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
PromiseType &calleePromise;
|
PromiseType &calleePromise;
|
||||||
|
|
||||||
|
private:
|
||||||
/** Every live invoker owns destruction of its callee coroutine frame in
|
/** Every live invoker owns destruction of its callee coroutine frame in
|
||||||
* ~NonPostingInvoker (via calleePromise.selfSchedHandle).
|
* ~NonPostingInvoker (via calleePromise.selfSchedHandle).
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -9,15 +9,99 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include <spinscale/spinLock.h>
|
||||||
#include <spinscale/co/coQutex.h>
|
#include <spinscale/co/coQutex.h>
|
||||||
#include <spinscale/co/promiseChainLink.h>
|
#include <spinscale/co/promiseChainLink.h>
|
||||||
#include <spinscale/co/promises.h>
|
#include <spinscale/co/promises.h>
|
||||||
|
|
||||||
namespace sscl::co {
|
namespace sscl::co {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
struct NonPostingPromise
|
struct NonPostingPromise
|
||||||
: public PromiseChainLink
|
: public PromiseChainLink,
|
||||||
|
public PostingPromiseReturnOps<NonPostingPromise<T>, T>
|
||||||
{
|
{
|
||||||
|
struct PostBackStatus
|
||||||
|
{
|
||||||
|
struct CalleeFlowExecutor;
|
||||||
|
struct CallerFlowExecutor;
|
||||||
|
friend struct CalleeFlowExecutor;
|
||||||
|
friend struct CallerFlowExecutor;
|
||||||
|
|
||||||
|
explicit PostBackStatus(NonPostingPromise &calleePromiseIn) noexcept
|
||||||
|
: calleePromise(calleePromiseIn)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void reset() noexcept
|
||||||
|
{
|
||||||
|
sscl::SpinLock::Guard guard(lock);
|
||||||
|
callerHasSetCallerSchedHandle = false;
|
||||||
|
calleeIsReadyToPostBack = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FlowExecutor
|
||||||
|
{
|
||||||
|
explicit FlowExecutor(PostBackStatus &parentIn) noexcept
|
||||||
|
: parent(parentIn)
|
||||||
|
{}
|
||||||
|
|
||||||
|
PostBackStatus &parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CalleeFlowExecutor
|
||||||
|
: public FlowExecutor
|
||||||
|
{
|
||||||
|
explicit CalleeFlowExecutor(PostBackStatus &parentIn) noexcept
|
||||||
|
: FlowExecutor(parentIn)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool operator()() noexcept
|
||||||
|
{
|
||||||
|
sscl::SpinLock::Guard guard(this->parent.lock);
|
||||||
|
this->parent.calleeIsReadyToPostBack = true;
|
||||||
|
if (this->parent.callerHasSetCallerSchedHandle) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CallerFlowExecutor
|
||||||
|
: public FlowExecutor
|
||||||
|
{
|
||||||
|
explicit CallerFlowExecutor(PostBackStatus &parentIn) noexcept
|
||||||
|
: FlowExecutor(parentIn)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool operator()() noexcept
|
||||||
|
{
|
||||||
|
sscl::SpinLock::Guard guard(this->parent.lock);
|
||||||
|
this->parent.callerHasSetCallerSchedHandle = true;
|
||||||
|
if (this->parent.calleeIsReadyToPostBack) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CalleeFlowExecutor getCalleeFlowExecutor() noexcept
|
||||||
|
{
|
||||||
|
return CalleeFlowExecutor(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
CallerFlowExecutor getCallerFlowExecutor() noexcept
|
||||||
|
{
|
||||||
|
return CallerFlowExecutor(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
NonPostingPromise &calleePromise;
|
||||||
|
|
||||||
|
private:
|
||||||
|
sscl::SpinLock lock;
|
||||||
|
bool callerHasSetCallerSchedHandle = false;
|
||||||
|
bool calleeIsReadyToPostBack = false;
|
||||||
|
};
|
||||||
|
|
||||||
/** Completion work must run from this awaiter's await_suspend, not
|
/** Completion work must run from this awaiter's await_suspend, not
|
||||||
* synchronously inside promise.final_suspend() before it returns: the
|
* synchronously inside promise.final_suspend() before it returns: the
|
||||||
* hidden coroutine segment index in the coroutine state is only advanced
|
* hidden coroutine segment index in the coroutine state is only advanced
|
||||||
@@ -26,16 +110,19 @@ struct NonPostingPromise
|
|||||||
struct FinalSuspendNonPostingInvoker
|
struct FinalSuspendNonPostingInvoker
|
||||||
: public std::suspend_always
|
: public std::suspend_always
|
||||||
{
|
{
|
||||||
explicit FinalSuspendNonPostingInvoker(NonPostingPromise &calleePromiseIn) noexcept
|
explicit FinalSuspendNonPostingInvoker(
|
||||||
|
NonPostingPromise &calleePromiseIn) noexcept
|
||||||
: calleePromise(calleePromiseIn)
|
: calleePromise(calleePromiseIn)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool await_suspend(std::coroutine_handle<> const) noexcept
|
std::coroutine_handle<> await_suspend(
|
||||||
|
std::coroutine_handle<> const) noexcept
|
||||||
{
|
{
|
||||||
if (calleePromise.callerLambda)
|
if (calleePromise.callerLambda)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
||||||
std::cout << "final_suspend" << ": " << std::this_thread::get_id()
|
std::cout << "final_suspend" << ": "
|
||||||
|
<< std::this_thread::get_id()
|
||||||
<< " Non-viral non-posting: invoking callerLambda directly.\n";
|
<< " Non-viral non-posting: invoking callerLambda directly.\n";
|
||||||
#endif
|
#endif
|
||||||
if (calleePromise.returnValues.myExceptionPtr) {
|
if (calleePromise.returnValues.myExceptionPtr) {
|
||||||
@@ -44,15 +131,29 @@ struct NonPostingPromise
|
|||||||
}
|
}
|
||||||
|
|
||||||
calleePromise.callerLambda();
|
calleePromise.callerLambda();
|
||||||
|
return std::noop_coroutine();
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
||||||
|
std::cout << "final_suspend" << ": " << std::this_thread::get_id()
|
||||||
|
<< " Viral non-posting: running CalleeFlowExecutor.\n";
|
||||||
|
#endif
|
||||||
|
const bool symmetricTransferToCaller =
|
||||||
|
calleePromise.postBackStatus.getCalleeFlowExecutor()();
|
||||||
|
|
||||||
|
if (symmetricTransferToCaller && calleePromise.callerSchedHandle) {
|
||||||
|
return calleePromise.callerSchedHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::noop_coroutine();
|
||||||
}
|
}
|
||||||
|
|
||||||
NonPostingPromise &calleePromise;
|
NonPostingPromise &calleePromise;
|
||||||
};
|
};
|
||||||
|
|
||||||
NonPostingPromise() noexcept
|
NonPostingPromise() noexcept
|
||||||
: returnValues()
|
: returnValues(),
|
||||||
|
postBackStatus(*this)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <typename... TailArgs>
|
template <typename... TailArgs>
|
||||||
@@ -61,13 +162,27 @@ struct NonPostingPromise
|
|||||||
std::function<void()> callerLambdaIn,
|
std::function<void()> callerLambdaIn,
|
||||||
TailArgs &&...) noexcept
|
TailArgs &&...) noexcept
|
||||||
: returnValues(callerExceptionPtr),
|
: returnValues(callerExceptionPtr),
|
||||||
callerLambda(std::move(callerLambdaIn))
|
callerLambda(std::move(callerLambdaIn)),
|
||||||
|
postBackStatus(*this)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <typename ObjectArg, typename... TailArgs>
|
||||||
|
requires (!std::same_as<std::remove_cvref_t<ObjectArg>, std::exception_ptr>)
|
||||||
|
NonPostingPromise(
|
||||||
|
ObjectArg &&,
|
||||||
|
std::exception_ptr &callerExceptionPtr,
|
||||||
|
std::function<void()> callerLambdaIn,
|
||||||
|
TailArgs &&...) noexcept
|
||||||
|
: NonPostingPromise(
|
||||||
|
callerExceptionPtr,
|
||||||
|
std::move(callerLambdaIn))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~NonPostingPromise() noexcept
|
~NonPostingPromise() noexcept
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
||||||
std::cout << __func__ << ": " << std::this_thread::get_id() << " Destructing.\n";
|
std::cout << __func__ << ": " << std::this_thread::get_id()
|
||||||
|
<< " Destructing.\n";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,9 +192,6 @@ struct NonPostingPromise
|
|||||||
auto final_suspend() noexcept
|
auto final_suspend() noexcept
|
||||||
{ return FinalSuspendNonPostingInvoker(*this); }
|
{ return FinalSuspendNonPostingInvoker(*this); }
|
||||||
|
|
||||||
void return_void() noexcept
|
|
||||||
{ return; }
|
|
||||||
|
|
||||||
void unhandled_exception() noexcept
|
void unhandled_exception() noexcept
|
||||||
{
|
{
|
||||||
returnValues.myExceptionPtr = std::current_exception();
|
returnValues.myExceptionPtr = std::current_exception();
|
||||||
@@ -90,16 +202,26 @@ struct NonPostingPromise
|
|||||||
eraseFirstMatchingAcquiredLock(coQutex);
|
eraseFirstMatchingAcquiredLock(coQutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PromiseChainLink *callerPromiseChainLink() const noexcept override
|
||||||
|
{ return callerChainLink; }
|
||||||
|
|
||||||
|
PromiseChainLink *callerPromiseChainLink() noexcept override
|
||||||
|
{ return callerChainLink; }
|
||||||
|
|
||||||
void setSelfSchedHandle(std::coroutine_handle<> schedHandle) noexcept
|
void setSelfSchedHandle(std::coroutine_handle<> schedHandle) noexcept
|
||||||
{
|
{ selfSchedHandle = schedHandle; }
|
||||||
selfSchedHandle = schedHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValues<void> returnValues;
|
void setCallerPromiseChainLink(PromiseChainLink *chainLink) noexcept
|
||||||
|
{ callerChainLink = chainLink; }
|
||||||
|
|
||||||
|
ReturnValues<T> returnValues;
|
||||||
std::function<void()> callerLambda;
|
std::function<void()> callerLambda;
|
||||||
|
PostBackStatus postBackStatus;
|
||||||
std::coroutine_handle<> selfSchedHandle;
|
std::coroutine_handle<> selfSchedHandle;
|
||||||
|
std::coroutine_handle<> callerSchedHandle;
|
||||||
|
PromiseChainLink *callerChainLink = nullptr;
|
||||||
|
|
||||||
template <typename>
|
template <typename, typename>
|
||||||
friend class NonPostingInvoker;
|
friend class NonPostingInvoker;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <typeinfo>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -267,6 +268,22 @@ struct PostingPromise
|
|||||||
postBackStatus(*this)
|
postBackStatus(*this)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
/** Member coroutines pass the implicit object parameter before explicit
|
||||||
|
* (exceptionPtr, callback, ...) args. Discard the object and delegate to
|
||||||
|
* the free-function constructor shape.
|
||||||
|
*/
|
||||||
|
template <typename ObjectArg, typename... TailArgs>
|
||||||
|
requires (!std::same_as<std::remove_cvref_t<ObjectArg>, std::exception_ptr>)
|
||||||
|
PostingPromise(
|
||||||
|
ObjectArg &&,
|
||||||
|
std::exception_ptr &_callerExceptionPtr,
|
||||||
|
std::function<void()> _callerLambda,
|
||||||
|
TailArgs &&...) noexcept
|
||||||
|
: PostingPromise(
|
||||||
|
_callerExceptionPtr,
|
||||||
|
std::move(_callerLambda))
|
||||||
|
{}
|
||||||
|
|
||||||
~PostingPromise() noexcept
|
~PostingPromise() noexcept
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
||||||
@@ -345,6 +362,19 @@ struct TaggedPostingPromise
|
|||||||
std::forward<TailArgs>(tailArgs)...)
|
std::forward<TailArgs>(tailArgs)...)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
template <typename ObjectArg, typename... TailArgs>
|
||||||
|
requires (!std::same_as<std::remove_cvref_t<ObjectArg>, std::exception_ptr>)
|
||||||
|
TaggedPostingPromise(
|
||||||
|
ObjectArg &&,
|
||||||
|
std::exception_ptr &_exceptionPtr,
|
||||||
|
std::function<void()> _callerLambda,
|
||||||
|
TailArgs &&... tailArgs) noexcept
|
||||||
|
: PostingPromise<T>(
|
||||||
|
_exceptionPtr,
|
||||||
|
std::move(_callerLambda),
|
||||||
|
std::forward<TailArgs>(tailArgs)...)
|
||||||
|
{}
|
||||||
|
|
||||||
auto initial_suspend() noexcept
|
auto initial_suspend() noexcept
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
#ifdef CONFIG_LIBSSCL_DEBUG_CO
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <boost/asio/io_service.hpp>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -14,9 +13,11 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <coroutine>
|
#include <coroutine>
|
||||||
#include <spinscale/cps/callback.h>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <boost/asio/io_service.hpp>
|
||||||
|
#include <boost/asio/post.hpp>
|
||||||
|
#include <spinscale/cps/callback.h>
|
||||||
|
|
||||||
namespace sscl {
|
namespace sscl {
|
||||||
|
|
||||||
@@ -165,21 +166,40 @@ public:
|
|||||||
|
|
||||||
struct ViralThreadLifetimeMgmtInvoker
|
struct ViralThreadLifetimeMgmtInvoker
|
||||||
{
|
{
|
||||||
|
struct AsyncState
|
||||||
|
{
|
||||||
|
std::atomic<bool> settled{false};
|
||||||
|
std::coroutine_handle<> callerSchedHandle;
|
||||||
|
};
|
||||||
|
|
||||||
ViralThreadLifetimeMgmtInvoker(
|
ViralThreadLifetimeMgmtInvoker(
|
||||||
ThreadOp _threadOp,
|
ThreadOp _threadOp,
|
||||||
PuppetThread &_parentThread,
|
PuppetThread &_parentThread,
|
||||||
const std::shared_ptr<PuppetThread> &_selfPtr = nullptr)
|
const std::shared_ptr<PuppetThread> &_selfPtr = nullptr)
|
||||||
: threadOp(_threadOp),
|
: threadOp(_threadOp),
|
||||||
|
asyncState(std::make_shared<AsyncState>()),
|
||||||
parentThread(_parentThread),
|
parentThread(_parentThread),
|
||||||
selfPtr(_selfPtr),
|
selfPtr(_selfPtr),
|
||||||
lifetimeMgmtCallback{
|
lifetimeMgmtCallback{
|
||||||
nullptr,
|
nullptr,
|
||||||
[this]()
|
[asyncState = asyncState]()
|
||||||
{
|
{
|
||||||
settled = true;
|
asyncState->settled.store(true, std::memory_order_release);
|
||||||
if (callerSchedHandle) {
|
|
||||||
callerSchedHandle.resume();
|
std::coroutine_handle<> handle =
|
||||||
|
asyncState->callerSchedHandle;
|
||||||
|
|
||||||
|
if (!handle) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Post resume to the puppeteer queue: direct resume() from
|
||||||
|
* within an asio completion handler can destroy adapter
|
||||||
|
* coroutine state while the handler is still unwinding.
|
||||||
|
*/
|
||||||
|
boost::asio::post(
|
||||||
|
ComponentThread::getPptr()->getIoService(),
|
||||||
|
[handle]() { handle.resume(); });
|
||||||
}}
|
}}
|
||||||
{
|
{
|
||||||
if (threadOp == ThreadOp::JOLT && selfPtr == nullptr)
|
if (threadOp == ThreadOp::JOLT && selfPtr == nullptr)
|
||||||
@@ -212,26 +232,32 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool await_ready() const noexcept { return settled; }
|
bool await_ready() const noexcept
|
||||||
|
{
|
||||||
|
return asyncState->settled.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
bool await_suspend(
|
bool await_suspend(
|
||||||
std::coroutine_handle<> _callerSchedHandle) noexcept
|
std::coroutine_handle<> _callerSchedHandle) noexcept
|
||||||
{
|
{
|
||||||
if (settled) { return false; }
|
if (asyncState->settled.load(std::memory_order_acquire)) {
|
||||||
callerSchedHandle = _callerSchedHandle;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
asyncState->callerSchedHandle = _callerSchedHandle;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void await_resume() noexcept {}
|
void await_resume() noexcept {}
|
||||||
|
|
||||||
ThreadOp threadOp;
|
ThreadOp threadOp;
|
||||||
bool settled = false;
|
std::shared_ptr<AsyncState> asyncState;
|
||||||
std::coroutine_handle<> callerSchedHandle;
|
|
||||||
PuppetThread &parentThread;
|
PuppetThread &parentThread;
|
||||||
const std::shared_ptr<PuppetThread> selfPtr;
|
const std::shared_ptr<PuppetThread> selfPtr;
|
||||||
cps::Callback<threadLifetimeMgmtOpCbFn> lifetimeMgmtCallback;
|
cps::Callback<threadLifetimeMgmtOpCbFn> lifetimeMgmtCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Thread lifetime management request invokers
|
||||||
ViralThreadLifetimeMgmtInvoker startThreadAReq()
|
ViralThreadLifetimeMgmtInvoker startThreadAReq()
|
||||||
{ return ViralThreadLifetimeMgmtInvoker(ThreadOp::START, *this); }
|
{ return ViralThreadLifetimeMgmtInvoker(ThreadOp::START, *this); }
|
||||||
ViralThreadLifetimeMgmtInvoker pauseThreadAReq()
|
ViralThreadLifetimeMgmtInvoker pauseThreadAReq()
|
||||||
|
|||||||
@@ -5,7 +5,10 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <spinscale/co/group.h>
|
||||||
#include <spinscale/co/invokers.h>
|
#include <spinscale/co/invokers.h>
|
||||||
#include <spinscale/componentThread.h>
|
#include <spinscale/componentThread.h>
|
||||||
|
|
||||||
@@ -19,22 +22,30 @@ public:
|
|||||||
const std::vector<std::shared_ptr<PuppetThread>> &threads);
|
const std::vector<std::shared_ptr<PuppetThread>> &threads);
|
||||||
~PuppetApplication() = default;
|
~PuppetApplication() = default;
|
||||||
|
|
||||||
co::NonViralNonPostingInvoker joltAllPuppetThreadsCReq(
|
co::ViralNonPostingInvoker<void> joltAllPuppetThreadsCReq(
|
||||||
std::exception_ptr &exceptionPtr, std::function<void()> callback);
|
std::exception_ptr &exceptionPtr, std::function<void()> callback);
|
||||||
co::NonViralNonPostingInvoker startAllPuppetThreadsCReq(
|
co::ViralNonPostingInvoker<void> startAllPuppetThreadsCReq(
|
||||||
std::exception_ptr &exceptionPtr, std::function<void()> callback);
|
std::exception_ptr &exceptionPtr, std::function<void()> callback);
|
||||||
co::NonViralNonPostingInvoker pauseAllPuppetThreadsCReq(
|
co::ViralNonPostingInvoker<void> pauseAllPuppetThreadsCReq(
|
||||||
std::exception_ptr &exceptionPtr, std::function<void()> callback);
|
std::exception_ptr &exceptionPtr, std::function<void()> callback);
|
||||||
co::NonViralNonPostingInvoker resumeAllPuppetThreadsCReq(
|
co::ViralNonPostingInvoker<void> resumeAllPuppetThreadsCReq(
|
||||||
std::exception_ptr &exceptionPtr, std::function<void()> callback);
|
std::exception_ptr &exceptionPtr, std::function<void()> callback);
|
||||||
co::NonViralNonPostingInvoker exitAllPuppetThreadsCReq(
|
co::ViralNonPostingInvoker<void> exitAllPuppetThreadsCReq(
|
||||||
std::exception_ptr &exceptionPtr, std::function<void()> callback);
|
std::exception_ptr &exceptionPtr, std::function<void()> callback);
|
||||||
|
|
||||||
// CPU distribution method
|
// CPU distribution method
|
||||||
void distributeAndPinThreadsAcrossCpus();
|
void distributeAndPinThreadsAcrossCpus();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Collection of PuppetThread instances
|
using PuppetLifetimeMgmtInvoker =
|
||||||
|
PuppetThread::ViralThreadLifetimeMgmtInvoker;
|
||||||
|
using PuppetLifetimeMgmtGroup = co::Group<PuppetLifetimeMgmtInvoker>;
|
||||||
|
|
||||||
|
void addAllPuppetLifetimeInvokersToGroup(
|
||||||
|
PuppetLifetimeMgmtGroup &group,
|
||||||
|
std::vector<PuppetLifetimeMgmtInvoker> &invokers,
|
||||||
|
PuppetThread::ThreadOp threadOp) const;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<PuppetThread>> componentThreads;
|
std::vector<std::shared_ptr<PuppetThread>> componentThreads;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,6 +68,13 @@ protected:
|
|||||||
* a synchronization point for the entire system initialization.
|
* a synchronization point for the entire system initialization.
|
||||||
*/
|
*/
|
||||||
bool threadsHaveBeenJolted = false;
|
bool threadsHaveBeenJolted = false;
|
||||||
|
|
||||||
|
private:
|
||||||
|
co::ViralNonPostingInvoker<void> allPuppetThreadsLifetimeOpCReq(
|
||||||
|
std::exception_ptr &exceptionPtr,
|
||||||
|
std::function<void()> callback,
|
||||||
|
PuppetThread::ThreadOp threadOp,
|
||||||
|
std::string_view emptyThreadsLogMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sscl
|
} // namespace sscl
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <spinscale/cps/asynchronousContinuation.h>
|
#include <spinscale/cps/asynchronousContinuation.h>
|
||||||
#include <spinscale/cps/callback.h>
|
#include <spinscale/cps/callback.h>
|
||||||
#include <spinscale/cps/callableTracer.h>
|
#include <spinscale/cps/callableTracer.h>
|
||||||
|
#include <spinscale/co/invokers.h>
|
||||||
#include <spinscale/component.h>
|
#include <spinscale/component.h>
|
||||||
#include <spinscale/componentThread.h>
|
#include <spinscale/componentThread.h>
|
||||||
|
|
||||||
|
|||||||
+75
-74
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
namespace sscl {
|
namespace sscl {
|
||||||
|
|
||||||
namespace puppet_application_detail {
|
namespace {
|
||||||
|
|
||||||
constexpr std::string_view noPuppetThreadsToStartLogMessage =
|
constexpr std::string_view noPuppetThreadsToStartLogMessage =
|
||||||
"Mrntt: No puppet threads to start";
|
"Mrntt: No puppet threads to start";
|
||||||
@@ -19,14 +19,18 @@ constexpr std::string_view noPuppetThreadsToResumeLogMessage =
|
|||||||
constexpr std::string_view noPuppetThreadsToExitLogMessage =
|
constexpr std::string_view noPuppetThreadsToExitLogMessage =
|
||||||
"Mrntt: No puppet threads to exit";
|
"Mrntt: No puppet threads to exit";
|
||||||
|
|
||||||
using PuppetLifetimeInvoker = PuppetThread::ViralThreadLifetimeMgmtInvoker;
|
} // namespace
|
||||||
using PuppetLifetimeGroup = co::Group<PuppetLifetimeInvoker>;
|
|
||||||
|
|
||||||
void addAllPuppetLifetimeInvokersToGroup(
|
PuppetApplication::PuppetApplication(
|
||||||
PuppetLifetimeGroup &group,
|
const std::vector<std::shared_ptr<PuppetThread>> &threads)
|
||||||
std::vector<PuppetLifetimeInvoker> &invokers,
|
: componentThreads(threads)
|
||||||
const std::vector<std::shared_ptr<PuppetThread>> &componentThreads,
|
{
|
||||||
PuppetThread::ThreadOp threadOp)
|
}
|
||||||
|
|
||||||
|
void PuppetApplication::addAllPuppetLifetimeInvokersToGroup(
|
||||||
|
PuppetLifetimeMgmtGroup &group,
|
||||||
|
std::vector<PuppetLifetimeMgmtInvoker> &invokers,
|
||||||
|
PuppetThread::ThreadOp threadOp) const
|
||||||
{
|
{
|
||||||
invokers.reserve(componentThreads.size());
|
invokers.reserve(componentThreads.size());
|
||||||
|
|
||||||
@@ -58,40 +62,8 @@ void addAllPuppetLifetimeInvokersToGroup(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
co::NonViralNonPostingInvoker genericAllPuppetThreadsLifetimeOpCReq(
|
co::ViralNonPostingInvoker<void>
|
||||||
const std::vector<std::shared_ptr<PuppetThread>> &componentThreads,
|
PuppetApplication::joltAllPuppetThreadsCReq(
|
||||||
PuppetThread::ThreadOp threadOp,
|
|
||||||
std::string_view emptyThreadsLogMessage,
|
|
||||||
[[maybe_unused]] std::exception_ptr &exceptionPtr,
|
|
||||||
[[maybe_unused]] std::function<void()> callback)
|
|
||||||
{
|
|
||||||
if (componentThreads.empty())
|
|
||||||
{
|
|
||||||
std::cout << emptyThreadsLogMessage << "\n";
|
|
||||||
co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PuppetLifetimeGroup group;
|
|
||||||
std::vector<PuppetLifetimeInvoker> invokers;
|
|
||||||
|
|
||||||
addAllPuppetLifetimeInvokersToGroup(
|
|
||||||
group, invokers, componentThreads, threadOp);
|
|
||||||
|
|
||||||
co_await group.getAwaitAllSettlementsInvoker();
|
|
||||||
group.checkForAndReThrowGroupExceptions();
|
|
||||||
|
|
||||||
co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace puppet_application_detail
|
|
||||||
|
|
||||||
PuppetApplication::PuppetApplication(
|
|
||||||
const std::vector<std::shared_ptr<PuppetThread>> &threads)
|
|
||||||
: componentThreads(threads)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
co::NonViralNonPostingInvoker PuppetApplication::joltAllPuppetThreadsCReq(
|
|
||||||
[[maybe_unused]] std::exception_ptr &exceptionPtr,
|
[[maybe_unused]] std::exception_ptr &exceptionPtr,
|
||||||
[[maybe_unused]] std::function<void()> callback)
|
[[maybe_unused]] std::function<void()> callback)
|
||||||
{
|
{
|
||||||
@@ -108,64 +80,94 @@ co::NonViralNonPostingInvoker PuppetApplication::joltAllPuppetThreadsCReq(
|
|||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
puppet_application_detail::PuppetLifetimeGroup group;
|
PuppetLifetimeMgmtGroup group;
|
||||||
std::vector<puppet_application_detail::PuppetLifetimeInvoker> invokers;
|
std::vector<PuppetLifetimeMgmtInvoker> invokers;
|
||||||
|
|
||||||
puppet_application_detail::addAllPuppetLifetimeInvokersToGroup(
|
addAllPuppetLifetimeInvokersToGroup(
|
||||||
group, invokers, componentThreads, PuppetThread::ThreadOp::JOLT);
|
group, invokers, PuppetThread::ThreadOp::JOLT);
|
||||||
|
PuppetLifetimeMgmtGroup::AwaitAllSettlementsInvoker groupAwaitAll(
|
||||||
co_await group.getAwaitAllSettlementsInvoker();
|
group);
|
||||||
|
co_await groupAwaitAll;
|
||||||
group.checkForAndReThrowGroupExceptions();
|
group.checkForAndReThrowGroupExceptions();
|
||||||
|
|
||||||
threadsHaveBeenJolted = true;
|
threadsHaveBeenJolted = true;
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
co::NonViralNonPostingInvoker PuppetApplication::startAllPuppetThreadsCReq(
|
co::ViralNonPostingInvoker<void>
|
||||||
std::exception_ptr &exceptionPtr, std::function<void()> callback)
|
PuppetApplication::allPuppetThreadsLifetimeOpCReq(
|
||||||
|
[[maybe_unused]] std::exception_ptr &exceptionPtr,
|
||||||
|
[[maybe_unused]] std::function<void()> callback,
|
||||||
|
PuppetThread::ThreadOp threadOp,
|
||||||
|
std::string_view emptyThreadsLogMessage)
|
||||||
{
|
{
|
||||||
return puppet_application_detail::genericAllPuppetThreadsLifetimeOpCReq(
|
if (componentThreads.empty())
|
||||||
componentThreads, PuppetThread::ThreadOp::START,
|
{
|
||||||
puppet_application_detail::noPuppetThreadsToStartLogMessage,
|
std::cout << emptyThreadsLogMessage << "\n";
|
||||||
exceptionPtr, callback);
|
co_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PuppetLifetimeMgmtGroup group;
|
||||||
|
std::vector<PuppetLifetimeMgmtInvoker> invokers;
|
||||||
|
|
||||||
|
addAllPuppetLifetimeInvokersToGroup(group, invokers, threadOp);
|
||||||
|
PuppetLifetimeMgmtGroup::AwaitAllSettlementsInvoker groupAwaitAll(
|
||||||
|
group);
|
||||||
|
co_await groupAwaitAll;
|
||||||
|
group.checkForAndReThrowGroupExceptions();
|
||||||
|
|
||||||
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
co::NonViralNonPostingInvoker PuppetApplication::pauseAllPuppetThreadsCReq(
|
co::ViralNonPostingInvoker<void>
|
||||||
|
PuppetApplication::startAllPuppetThreadsCReq(
|
||||||
std::exception_ptr &exceptionPtr, std::function<void()> callback)
|
std::exception_ptr &exceptionPtr, std::function<void()> callback)
|
||||||
{
|
{
|
||||||
return puppet_application_detail::genericAllPuppetThreadsLifetimeOpCReq(
|
return allPuppetThreadsLifetimeOpCReq(
|
||||||
componentThreads, PuppetThread::ThreadOp::PAUSE,
|
exceptionPtr, std::move(callback),
|
||||||
puppet_application_detail::noPuppetThreadsToPauseLogMessage,
|
PuppetThread::ThreadOp::START,
|
||||||
exceptionPtr, callback);
|
noPuppetThreadsToStartLogMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
co::NonViralNonPostingInvoker PuppetApplication::resumeAllPuppetThreadsCReq(
|
co::ViralNonPostingInvoker<void>
|
||||||
|
PuppetApplication::pauseAllPuppetThreadsCReq(
|
||||||
std::exception_ptr &exceptionPtr, std::function<void()> callback)
|
std::exception_ptr &exceptionPtr, std::function<void()> callback)
|
||||||
{
|
{
|
||||||
return puppet_application_detail::genericAllPuppetThreadsLifetimeOpCReq(
|
return allPuppetThreadsLifetimeOpCReq(
|
||||||
componentThreads, PuppetThread::ThreadOp::RESUME,
|
exceptionPtr, std::move(callback),
|
||||||
puppet_application_detail::noPuppetThreadsToResumeLogMessage,
|
PuppetThread::ThreadOp::PAUSE,
|
||||||
exceptionPtr, callback);
|
noPuppetThreadsToPauseLogMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
co::NonViralNonPostingInvoker PuppetApplication::exitAllPuppetThreadsCReq(
|
co::ViralNonPostingInvoker<void>
|
||||||
|
PuppetApplication::resumeAllPuppetThreadsCReq(
|
||||||
|
std::exception_ptr &exceptionPtr, std::function<void()> callback)
|
||||||
|
{
|
||||||
|
return allPuppetThreadsLifetimeOpCReq(
|
||||||
|
exceptionPtr, std::move(callback),
|
||||||
|
PuppetThread::ThreadOp::RESUME,
|
||||||
|
noPuppetThreadsToResumeLogMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
co::ViralNonPostingInvoker<void>
|
||||||
|
PuppetApplication::exitAllPuppetThreadsCReq(
|
||||||
[[maybe_unused]] std::exception_ptr &exceptionPtr,
|
[[maybe_unused]] std::exception_ptr &exceptionPtr,
|
||||||
[[maybe_unused]] std::function<void()> callback)
|
[[maybe_unused]] std::function<void()> callback)
|
||||||
{
|
{
|
||||||
if (componentThreads.empty())
|
if (componentThreads.empty())
|
||||||
{
|
{
|
||||||
std::cout << puppet_application_detail::noPuppetThreadsToExitLogMessage
|
std::cout << noPuppetThreadsToExitLogMessage << "\n";
|
||||||
<< "\n";
|
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
puppet_application_detail::PuppetLifetimeGroup group;
|
PuppetLifetimeMgmtGroup group;
|
||||||
std::vector<puppet_application_detail::PuppetLifetimeInvoker> invokers;
|
std::vector<PuppetLifetimeMgmtInvoker> invokers;
|
||||||
|
|
||||||
puppet_application_detail::addAllPuppetLifetimeInvokersToGroup(
|
addAllPuppetLifetimeInvokersToGroup(
|
||||||
group, invokers, componentThreads, PuppetThread::ThreadOp::EXIT);
|
group, invokers, PuppetThread::ThreadOp::EXIT);
|
||||||
|
PuppetLifetimeMgmtGroup::AwaitAllSettlementsInvoker groupAwaitAll(
|
||||||
co_await group.getAwaitAllSettlementsInvoker();
|
group);
|
||||||
|
co_await groupAwaitAll;
|
||||||
group.checkForAndReThrowGroupExceptions();
|
group.checkForAndReThrowGroupExceptions();
|
||||||
|
|
||||||
for (auto &thread : componentThreads) {
|
for (auto &thread : componentThreads) {
|
||||||
@@ -179,7 +181,6 @@ void PuppetApplication::distributeAndPinThreadsAcrossCpus()
|
|||||||
{
|
{
|
||||||
int cpuCount = ComponentThread::getAvailableCpuCount();
|
int cpuCount = ComponentThread::getAvailableCpuCount();
|
||||||
|
|
||||||
// Distribute and pin threads across CPUs
|
|
||||||
int threadIndex = 0;
|
int threadIndex = 0;
|
||||||
for (auto& thread : componentThreads)
|
for (auto& thread : componentThreads)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user