mirror of
https://github.com/latentPrion/libspinscale.git
synced 2026-06-23 19:48:32 +00:00
Boost.ASIO: update io_service=>io_context
This commit is contained in:
@@ -76,6 +76,7 @@ find_package(Threads REQUIRED)
|
|||||||
|
|
||||||
# Create the library
|
# Create the library
|
||||||
add_library(spinscale SHARED
|
add_library(spinscale SHARED
|
||||||
|
src/boostAsioLinkageFix.cpp
|
||||||
src/qutex.cpp
|
src/qutex.cpp
|
||||||
src/componentThread.cpp
|
src/componentThread.cpp
|
||||||
src/component.cpp
|
src/component.cpp
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
|
|
||||||
#include <spinscale/componentThread.h>
|
#include <spinscale/componentThread.h>
|
||||||
@@ -31,7 +31,7 @@ public:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit WaitingCoroutineBase(
|
explicit WaitingCoroutineBase(
|
||||||
boost::asio::io_service &callerIoContextIn) noexcept
|
boost::asio::io_context &callerIoContextIn) noexcept
|
||||||
: callerIoContext(callerIoContextIn)
|
: callerIoContext(callerIoContextIn)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ public:
|
|||||||
virtual void post() noexcept = 0;
|
virtual void post() noexcept = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
boost::asio::io_service &callerIoContext;
|
boost::asio::io_context &callerIoContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Promise>
|
template <typename Promise>
|
||||||
@@ -49,7 +49,7 @@ public:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TypedWaitingCoroutine(
|
TypedWaitingCoroutine(
|
||||||
boost::asio::io_service &callerIoContextIn,
|
boost::asio::io_context &callerIoContextIn,
|
||||||
std::coroutine_handle<Promise> callerSchedHandleIn) noexcept
|
std::coroutine_handle<Promise> callerSchedHandleIn) noexcept
|
||||||
: WaitingCoroutineBase(callerIoContextIn),
|
: WaitingCoroutineBase(callerIoContextIn),
|
||||||
callerSchedHandle(callerSchedHandleIn)
|
callerSchedHandle(callerSchedHandleIn)
|
||||||
@@ -83,8 +83,8 @@ public:
|
|||||||
template <typename Promise>
|
template <typename Promise>
|
||||||
bool await_suspend(std::coroutine_handle<Promise> cvCallerSchedHandle) noexcept
|
bool await_suspend(std::coroutine_handle<Promise> cvCallerSchedHandle) noexcept
|
||||||
{
|
{
|
||||||
boost::asio::io_service &cvCallerIoContext =
|
boost::asio::io_context &cvCallerIoContext =
|
||||||
sscl::ComponentThread::getSelf()->getIoService();
|
sscl::ComponentThread::getSelf()->getIoContext();
|
||||||
|
|
||||||
sscl::SpinLock::Guard guard(parentCv.spinLock);
|
sscl::SpinLock::Guard guard(parentCv.spinLock);
|
||||||
if (parentCv.isSignaled) {
|
if (parentCv.isSignaled) {
|
||||||
@@ -130,8 +130,8 @@ public:
|
|||||||
template <typename Promise>
|
template <typename Promise>
|
||||||
DecisionFactors awaitSuspend(std::coroutine_handle<Promise> cvCallerSchedHandle) noexcept
|
DecisionFactors awaitSuspend(std::coroutine_handle<Promise> cvCallerSchedHandle) noexcept
|
||||||
{
|
{
|
||||||
boost::asio::io_service &cvCallerIoContext =
|
boost::asio::io_context &cvCallerIoContext =
|
||||||
sscl::ComponentThread::getSelf()->getIoService();
|
sscl::ComponentThread::getSelf()->getIoContext();
|
||||||
|
|
||||||
parentCv.spinLock.acquire();
|
parentCv.spinLock.acquire();
|
||||||
if (parentCv.isSignaled)
|
if (parentCv.isSignaled)
|
||||||
@@ -197,7 +197,7 @@ public:
|
|||||||
template <typename Promise>
|
template <typename Promise>
|
||||||
void enqueueWaitingCoroutine(
|
void enqueueWaitingCoroutine(
|
||||||
std::coroutine_handle<Promise> handle,
|
std::coroutine_handle<Promise> handle,
|
||||||
boost::asio::io_service &ctx) noexcept
|
boost::asio::io_context &ctx) noexcept
|
||||||
{
|
{
|
||||||
waitingCoroutines.push_back(
|
waitingCoroutines.push_back(
|
||||||
std::make_unique<TypedWaitingCoroutine<Promise>>(ctx, handle));
|
std::make_unique<TypedWaitingCoroutine<Promise>>(ctx, handle));
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
|
|
||||||
#include <spinscale/componentThread.h>
|
#include <spinscale/componentThread.h>
|
||||||
@@ -56,7 +56,7 @@ public:
|
|||||||
{
|
{
|
||||||
WaitingCoroutine(
|
WaitingCoroutine(
|
||||||
std::coroutine_handle<void> _callerSchedHandle,
|
std::coroutine_handle<void> _callerSchedHandle,
|
||||||
boost::asio::io_service &_callerIoContext,
|
boost::asio::io_context &_callerIoContext,
|
||||||
PromiseChainLink &_waitingPromise) noexcept
|
PromiseChainLink &_waitingPromise) noexcept
|
||||||
: callerSchedHandle(_callerSchedHandle),
|
: callerSchedHandle(_callerSchedHandle),
|
||||||
callerIoContext(_callerIoContext),
|
callerIoContext(_callerIoContext),
|
||||||
@@ -64,7 +64,7 @@ public:
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
std::coroutine_handle<void> callerSchedHandle;
|
std::coroutine_handle<void> callerSchedHandle;
|
||||||
boost::asio::io_service &callerIoContext;
|
boost::asio::io_context &callerIoContext;
|
||||||
PromiseChainLink &waitingPromise;
|
PromiseChainLink &waitingPromise;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ public:
|
|||||||
}
|
}
|
||||||
coQutex.waitingCoroutines.emplace_back(
|
coQutex.waitingCoroutines.emplace_back(
|
||||||
std::coroutine_handle<void>::from_address(callerSchedHandle.address()),
|
std::coroutine_handle<void>::from_address(callerSchedHandle.address()),
|
||||||
sscl::ComponentThread::getSelf()->getIoService(),
|
sscl::ComponentThread::getSelf()->getIoContext(),
|
||||||
*acquirerChainLink);
|
*acquirerChainLink);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
|
|
||||||
#include <spinscale/componentThread.h>
|
#include <spinscale/componentThread.h>
|
||||||
@@ -486,7 +486,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 ComponentThread::getSelf()->getIoService().
|
* post()ing to ComponentThread::getSelf()->getIoContext().
|
||||||
*
|
*
|
||||||
* EXPLANATION:
|
* EXPLANATION:
|
||||||
* However, in order to ensure that we keep this adapter coro
|
* However, in order to ensure that we keep this adapter coro
|
||||||
@@ -494,7 +494,7 @@ struct Group
|
|||||||
* directly calling the handle.
|
* directly calling the handle.
|
||||||
*/
|
*/
|
||||||
boost::asio::post(
|
boost::asio::post(
|
||||||
sscl::ComponentThread::getSelf()->getIoService(),
|
sscl::ComponentThread::getSelf()->getIoContext(),
|
||||||
groupAwaiterSchedHandleToWake);
|
groupAwaiterSchedHandleToWake);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
|
|
||||||
#include <spinscale/componentThread.h>
|
#include <spinscale/componentThread.h>
|
||||||
@@ -124,19 +124,19 @@ struct PostingPromise
|
|||||||
: public std::suspend_always
|
: public std::suspend_always
|
||||||
{
|
{
|
||||||
InitialSuspendPostingInvoker(
|
InitialSuspendPostingInvoker(
|
||||||
boost::asio::io_service &targetIoServiceIn,
|
boost::asio::io_context &targetIoContextIn,
|
||||||
std::coroutine_handle<> targetSchedHandleIn) noexcept
|
std::coroutine_handle<> targetSchedHandleIn) noexcept
|
||||||
: targetIoService(targetIoServiceIn),
|
: targetIoContext(targetIoContextIn),
|
||||||
targetSchedHandle(targetSchedHandleIn)
|
targetSchedHandle(targetSchedHandleIn)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool await_suspend(std::coroutine_handle<> const) noexcept
|
bool await_suspend(std::coroutine_handle<> const) noexcept
|
||||||
{
|
{
|
||||||
boost::asio::post(targetIoService, targetSchedHandle);
|
boost::asio::post(targetIoContext, targetSchedHandle);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::io_service &targetIoService;
|
boost::asio::io_context &targetIoContext;
|
||||||
std::coroutine_handle<> targetSchedHandle;
|
std::coroutine_handle<> targetSchedHandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -253,8 +253,8 @@ struct PostingPromise
|
|||||||
|
|
||||||
ReturnValues<T> returnValues;
|
ReturnValues<T> returnValues;
|
||||||
std::function<void()> callerLambda;
|
std::function<void()> callerLambda;
|
||||||
boost::asio::io_service &callerIoContext =
|
boost::asio::io_context &callerIoContext =
|
||||||
sscl::ComponentThread::getSelf()->getIoService();
|
sscl::ComponentThread::getSelf()->getIoContext();
|
||||||
std::coroutine_handle<> selfSchedHandle;
|
std::coroutine_handle<> selfSchedHandle;
|
||||||
std::coroutine_handle<void> callerSchedHandle;
|
std::coroutine_handle<void> callerSchedHandle;
|
||||||
PromiseChainLink *callerChainLink = nullptr;
|
PromiseChainLink *callerChainLink = nullptr;
|
||||||
@@ -315,7 +315,7 @@ struct TaggedPostingPromise
|
|||||||
std::cout << __func__ << ": " << std::this_thread::get_id() << " Returning InitialSuspendPostingInvoker.\n";
|
std::cout << __func__ << ": " << std::this_thread::get_id() << " Returning InitialSuspendPostingInvoker.\n";
|
||||||
#endif
|
#endif
|
||||||
return typename PostingPromise<T>::InitialSuspendPostingInvoker(
|
return typename PostingPromise<T>::InitialSuspendPostingInvoker(
|
||||||
ThreadTag::io_service(),
|
ThreadTag::io_context(),
|
||||||
this->selfSchedHandle);
|
this->selfSchedHandle);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include <coroutine>
|
#include <coroutine>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
#include <spinscale/cps/callback.h>
|
#include <spinscale/cps/callback.h>
|
||||||
|
|
||||||
@@ -36,7 +36,8 @@ class ComponentThread
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
ComponentThread(ThreadId _id, std::string _name)
|
ComponentThread(ThreadId _id, std::string _name)
|
||||||
: id(_id), name(std::move(_name)), work(io_service), keepLooping(true)
|
: id(_id), name(std::move(_name)),
|
||||||
|
work(boost::asio::make_work_guard(io_context)), keepLooping(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -44,7 +45,7 @@ public:
|
|||||||
|
|
||||||
void cleanup(void);
|
void cleanup(void);
|
||||||
|
|
||||||
boost::asio::io_service& getIoService(void) { return io_service; }
|
boost::asio::io_context& getIoContext(void) { return io_context; }
|
||||||
|
|
||||||
static const std::shared_ptr<ComponentThread> getSelf(void);
|
static const std::shared_ptr<ComponentThread> getSelf(void);
|
||||||
static bool tlsInitialized(void);
|
static bool tlsInitialized(void);
|
||||||
@@ -66,8 +67,9 @@ public:
|
|||||||
public:
|
public:
|
||||||
ThreadId id;
|
ThreadId id;
|
||||||
std::string name;
|
std::string name;
|
||||||
boost::asio::io_service io_service;
|
boost::asio::io_context io_context;
|
||||||
boost::asio::io_service::work work;
|
boost::asio::executor_work_guard<
|
||||||
|
boost::asio::io_context::executor_type> work;
|
||||||
std::atomic<bool> keepLooping;
|
std::atomic<bool> keepLooping;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -153,7 +155,7 @@ public:
|
|||||||
preJoltHookFn preJoltFn)
|
preJoltHookFn preJoltFn)
|
||||||
: ComponentThread(_id, std::move(name)),
|
: ComponentThread(_id, std::move(name)),
|
||||||
pinnedCpuId(-1),
|
pinnedCpuId(-1),
|
||||||
pause_work(pause_io_service),
|
pause_work(boost::asio::make_work_guard(pause_io_context)),
|
||||||
entryFnArguments(*this, component, preJoltFn),
|
entryFnArguments(*this, component, preJoltFn),
|
||||||
thread(std::move(entryPoint), std::cref(entryFnArguments))
|
thread(std::move(entryPoint), std::cref(entryFnArguments))
|
||||||
{}
|
{}
|
||||||
@@ -198,7 +200,7 @@ public:
|
|||||||
* coroutine state while the handler is still unwinding.
|
* coroutine state while the handler is still unwinding.
|
||||||
*/
|
*/
|
||||||
boost::asio::post(
|
boost::asio::post(
|
||||||
ComponentThread::getPptr()->getIoService(),
|
ComponentThread::getPptr()->getIoContext(),
|
||||||
[handle]() { handle.resume(); });
|
[handle]() { handle.resume(); });
|
||||||
}}
|
}}
|
||||||
{
|
{
|
||||||
@@ -296,8 +298,9 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
int pinnedCpuId;
|
int pinnedCpuId;
|
||||||
boost::asio::io_service pause_io_service;
|
boost::asio::io_context pause_io_context;
|
||||||
boost::asio::io_service::work pause_work;
|
boost::asio::executor_work_guard<
|
||||||
|
boost::asio::io_context::executor_type> pause_work;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EntryFnArguments entryFnArguments;
|
EntryFnArguments entryFnArguments;
|
||||||
|
|||||||
@@ -3,34 +3,35 @@
|
|||||||
|
|
||||||
#include <boostAsioLinkageFix.h>
|
#include <boostAsioLinkageFix.h>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
|
#include <boost/asio/post.hpp>
|
||||||
|
|
||||||
namespace sscl::cps {
|
namespace sscl::cps {
|
||||||
|
|
||||||
class AsynchronousBridge
|
class AsynchronousBridge
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AsynchronousBridge(boost::asio::io_service &io_service)
|
AsynchronousBridge(boost::asio::io_context &io_context)
|
||||||
: isAsyncOperationComplete(false), io_service(io_service)
|
: isAsyncOperationComplete(false), io_context(io_context)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void setAsyncOperationComplete(void)
|
void setAsyncOperationComplete(void)
|
||||||
{
|
{
|
||||||
/** EXPLANATION:
|
/** EXPLANATION:
|
||||||
* This empty post()ed message is necessary to ensure that the thread
|
* This empty post()ed message is necessary to ensure that the thread
|
||||||
* that's waiting on the io_service is signaled to wake up and check
|
* that's waiting on the io_context is signaled to wake up and check
|
||||||
* the io_service's queue.
|
* the io_context's queue.
|
||||||
*/
|
*/
|
||||||
isAsyncOperationComplete.store(true);
|
isAsyncOperationComplete.store(true);
|
||||||
io_service.post([]{});
|
boost::asio::post(io_context, []{});
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitForAsyncOperationCompleteOrIoServiceStopped(void)
|
void waitForAsyncOperationCompleteOrIoContextStopped(void)
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
io_service.run_one();
|
io_context.run_one();
|
||||||
if (isAsyncOperationComplete.load() || io_service.stopped())
|
if (isAsyncOperationComplete.load() || io_context.stopped())
|
||||||
{ break; }
|
{ break; }
|
||||||
|
|
||||||
/** EXPLANATION:
|
/** EXPLANATION:
|
||||||
@@ -45,12 +46,12 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool exitedBecauseIoServiceStopped(void) const
|
bool exitedBecauseIoContextStopped(void) const
|
||||||
{ return io_service.stopped(); }
|
{ return io_context.stopped(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic<bool> isAsyncOperationComplete;
|
std::atomic<bool> isAsyncOperationComplete;
|
||||||
boost::asio::io_service &io_service;
|
boost::asio::io_context &io_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sscl::cps
|
} // namespace sscl::cps
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ public:
|
|||||||
* LockedNonPostedAsynchronousContinuation because the only way to implement
|
* LockedNonPostedAsynchronousContinuation because the only way to implement
|
||||||
* non-posted locking would be via busy-spinning or sleeplocks. This would
|
* non-posted locking would be via busy-spinning or sleeplocks. This would
|
||||||
* eliminate the throughput advantage from our Qspinning mechanism, which
|
* eliminate the throughput advantage from our Qspinning mechanism, which
|
||||||
* relies on re-posting to the io_service queue when locks are unavailable.
|
* relies on re-posting to the io_context queue when locks are unavailable.
|
||||||
*/
|
*/
|
||||||
template <class OriginalCbFnT>
|
template <class OriginalCbFnT>
|
||||||
class NonPostedAsynchronousContinuation
|
class NonPostedAsynchronousContinuation
|
||||||
@@ -141,7 +141,7 @@ public:
|
|||||||
if (AsynchronousContinuation<OriginalCbFnT>::originalCallback
|
if (AsynchronousContinuation<OriginalCbFnT>::originalCallback
|
||||||
.callbackFn)
|
.callbackFn)
|
||||||
{
|
{
|
||||||
caller->getIoService().post(
|
boost::asio::post(caller->getIoContext(),
|
||||||
STC(std::bind(
|
STC(std::bind(
|
||||||
AsynchronousContinuation<OriginalCbFnT>::originalCallback
|
AsynchronousContinuation<OriginalCbFnT>::originalCallback
|
||||||
.callbackFn,
|
.callbackFn,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace sscl::cps {
|
|||||||
*
|
*
|
||||||
* This class wraps any callable object with metadata (caller function name,
|
* This class wraps any callable object with metadata (caller function name,
|
||||||
* line number, and return addresses) to help debug cases where callables
|
* line number, and return addresses) to help debug cases where callables
|
||||||
* posted to boost::asio::io_service have gone out of scope. The metadata
|
* posted to boost::asio::io_context have gone out of scope. The metadata
|
||||||
* can be accessed from the callable's address when debugging.
|
* can be accessed from the callable's address when debugging.
|
||||||
*/
|
*/
|
||||||
class CallableTracer
|
class CallableTracer
|
||||||
@@ -100,7 +100,7 @@ private:
|
|||||||
* - Fallback: nullptr for return addresses
|
* - Fallback: nullptr for return addresses
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* thread->getIoService().post(
|
* boost::asio::post(thread->getIoContext(),
|
||||||
* STC(std::bind(&SomeClass::method, this, arg1, arg2)));
|
* STC(std::bind(&SomeClass::method, this, arg1, arg2)));
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_DEBUG_TRACE_CALLABLES
|
#ifdef CONFIG_DEBUG_TRACE_CALLABLES
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ public:
|
|||||||
* time it will leave the qutexQ is when the program terminates.
|
* time it will leave the qutexQ is when the program terminates.
|
||||||
*
|
*
|
||||||
* I'm not sure we'll actually cancal all in-flight async sequences --
|
* I'm not sure we'll actually cancal all in-flight async sequences --
|
||||||
* and especially not all those that aren't even in any io_service queues.
|
* and especially not all those that aren't even in any io_context queues.
|
||||||
* To whatever extent these objects get cleaned up, they'll probably be
|
* To whatever extent these objects get cleaned up, they'll probably be
|
||||||
* cleaned up in the qutexQ's std::list destructor -- and that won't
|
* cleaned up in the qutexQ's std::list destructor -- and that won't
|
||||||
* execute any fancy cleanup logic. It'll just clear() out the list.
|
* execute any fancy cleanup logic. It'll just clear() out the list.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public:
|
|||||||
virtual List::iterator getLockvokerIteratorForQutex(Qutex& qutex) const = 0;
|
virtual List::iterator getLockvokerIteratorForQutex(Qutex& qutex) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Awaken this lockvoker by posting it to its io_service
|
* @brief Awaken this lockvoker by posting it to its io_context
|
||||||
* @param forceAwaken If true, post even if already awake
|
* @param forceAwaken If true, post even if already awake
|
||||||
*/
|
*/
|
||||||
virtual void awaken(bool forceAwaken = false) = 0;
|
virtual void awaken(bool forceAwaken = false) = 0;
|
||||||
@@ -55,12 +55,12 @@ public:
|
|||||||
*
|
*
|
||||||
* Compare by the address of the continuation objects. Why?
|
* Compare by the address of the continuation objects. Why?
|
||||||
* Because there's no guarantee that the lockvoker object that was
|
* Because there's no guarantee that the lockvoker object that was
|
||||||
* passed in by the io_service invocation is the same object as that
|
* passed in by the io_context invocation is the same object as that
|
||||||
* which is in the qutexQs. Especially because we make_shared() a
|
* which is in the qutexQs. Especially because we make_shared() a
|
||||||
* copy when registerInQutexQueues()ing.
|
* copy when registerInQutexQueues()ing.
|
||||||
*
|
*
|
||||||
* Generally when we "wake" a lockvoker by enqueuing it, boost's
|
* Generally when we "wake" a lockvoker by enqueuing it, boost's
|
||||||
* io_service::post will copy the lockvoker object.
|
* io_context::post will copy the lockvoker object.
|
||||||
*/
|
*/
|
||||||
bool operator==(const LockerAndInvokerBase &other) const
|
bool operator==(const LockerAndInvokerBase &other) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public:
|
|||||||
* @brief LockerAndInvoker - Template class for lockvoking mechanism
|
* @brief LockerAndInvoker - Template class for lockvoking mechanism
|
||||||
*
|
*
|
||||||
* This class wraps a std::bind result and provides locking functionality.
|
* This class wraps a std::bind result and provides locking functionality.
|
||||||
* When locks cannot be acquired, the object re-posts itself to the io_service
|
* When locks cannot be acquired, the object re-posts itself to the io_context
|
||||||
* queue, implementing the "spinqueueing" pattern.
|
* queue, implementing the "spinqueueing" pattern.
|
||||||
*/
|
*/
|
||||||
template <class InvocationTargetT>
|
template <class InvocationTargetT>
|
||||||
@@ -74,10 +74,10 @@ public:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Constructor that immediately posts to io_service
|
* @brief Constructor that immediately posts to io_context
|
||||||
* @param serializedContinuation Reference to the serialized continuation
|
* @param serializedContinuation Reference to the serialized continuation
|
||||||
* containing LockSet and target io_service
|
* containing LockSet and target io_context
|
||||||
* @param target The ComponentThread whose io_service to post to
|
* @param target The ComponentThread whose io_context to post to
|
||||||
* @param invocationTarget The std::bind result to invoke when locks are acquired
|
* @param invocationTarget The std::bind result to invoke when locks are acquired
|
||||||
*/
|
*/
|
||||||
LockerAndInvoker(
|
LockerAndInvoker(
|
||||||
@@ -127,7 +127,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Awaken this lockvoker by posting it to its io_service
|
* @brief Awaken this lockvoker by posting it to its io_context
|
||||||
* @param forceAwaken If true, post even if already awake
|
* @param forceAwaken If true, post even if already awake
|
||||||
*/
|
*/
|
||||||
void awaken(bool forceAwaken = false) override
|
void awaken(bool forceAwaken = false) override
|
||||||
@@ -138,7 +138,7 @@ public:
|
|||||||
if (prevVal == true && !forceAwaken)
|
if (prevVal == true && !forceAwaken)
|
||||||
{ return; }
|
{ return; }
|
||||||
|
|
||||||
target->getIoService().post(*this);
|
boost::asio::post(target->getIoContext(), *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getLockSetSize() const override
|
size_t getLockSetSize() const override
|
||||||
@@ -161,14 +161,14 @@ public:
|
|||||||
* the AsyncContinuation sh_ptr (which the Lockvoker contains within
|
* the AsyncContinuation sh_ptr (which the Lockvoker contains within
|
||||||
* itself) alive without wasting too much memory.
|
* itself) alive without wasting too much memory.
|
||||||
*
|
*
|
||||||
* This way the io_service objects can remove the lockvoker from
|
* This way the io_context objects can remove the lockvoker from
|
||||||
* their queues and there'll be a copy of the lockvoker in each
|
* their queues and there'll be a copy of the lockvoker in each
|
||||||
* Qutex's queue.
|
* Qutex's queue.
|
||||||
*
|
*
|
||||||
* For non-serialized, posted continuations, they won't be removed
|
* For non-serialized, posted continuations, they won't be removed
|
||||||
* from the io_service queue until they're executed, so there's no
|
* from the io_context queue until they're executed, so there's no
|
||||||
* need to create copies of them. Lockvokers are removed from their
|
* need to create copies of them. Lockvokers are removed from their
|
||||||
* io_service, potentially without being executed if they fail to
|
* io_context, potentially without being executed if they fail to
|
||||||
* acquire all locks.
|
* acquire all locks.
|
||||||
*/
|
*/
|
||||||
void registerInLockSet()
|
void registerInLockSet()
|
||||||
@@ -185,7 +185,7 @@ public:
|
|||||||
*
|
*
|
||||||
* Sets isAwake=true before calling awaken with forceAwaken to ensure
|
* Sets isAwake=true before calling awaken with forceAwaken to ensure
|
||||||
* that none of the locks we just registered with awaken()s a duplicate
|
* that none of the locks we just registered with awaken()s a duplicate
|
||||||
* copy of this lockvoker on the io_service.
|
* copy of this lockvoker on the io_context.
|
||||||
*/
|
*/
|
||||||
void firstWake()
|
void firstWake()
|
||||||
{
|
{
|
||||||
@@ -213,8 +213,17 @@ public:
|
|||||||
{ return isDeadlockLikely(); }
|
{ return isDeadlockLikely(); }
|
||||||
|
|
||||||
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
|
#ifdef CONFIG_ENABLE_DEBUG_LOCKS
|
||||||
struct obsolete {
|
friend struct obsolete;
|
||||||
bool traceContinuationHistoryForGridlockOn(Qutex &firstFailedQutex);
|
|
||||||
|
struct obsolete
|
||||||
|
{
|
||||||
|
explicit obsolete(LockerAndInvoker &_parent) : parent(_parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool traceContinuationHistoryForGridlockOn(
|
||||||
|
Qutex &firstFailedQutex);
|
||||||
|
|
||||||
|
LockerAndInvoker &parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool traceContinuationHistoryForDeadlockOn(Qutex &firstFailedQutex);
|
bool traceContinuationHistoryForDeadlockOn(Qutex &firstFailedQutex);
|
||||||
@@ -435,7 +444,8 @@ SerializedAsynchronousContinuation<OriginalCbFnT>
|
|||||||
* should eventually be able to acquire that lock.
|
* should eventually be able to acquire that lock.
|
||||||
*/
|
*/
|
||||||
for (std::shared_ptr<AsynchronousContinuationChainLink> currContin =
|
for (std::shared_ptr<AsynchronousContinuationChainLink> currContin =
|
||||||
this->serializedContinuation.getCallersContinuationShPtr();
|
parent.serializedContinuation
|
||||||
|
.getCallersContinuationShPtr();
|
||||||
currContin != nullptr;
|
currContin != nullptr;
|
||||||
currContin = currContin->getCallersContinuationShPtr())
|
currContin = currContin->getCallersContinuationShPtr())
|
||||||
{
|
{
|
||||||
@@ -484,7 +494,7 @@ void SerializedAsynchronousContinuation<OriginalCbFnT>
|
|||||||
if (!serializedContinuation.requiredLocks.tryAcquireOrBackOff(
|
if (!serializedContinuation.requiredLocks.tryAcquireOrBackOff(
|
||||||
*this, firstFailedQutexRet))
|
*this, firstFailedQutexRet))
|
||||||
{
|
{
|
||||||
// Just allow this lockvoker to be dropped from its io_service.
|
// Just allow this lockvoker to be dropped from its io_context.
|
||||||
allowAwakening();
|
allowAwakening();
|
||||||
if (!deadlockLikely && !gridlockLikely)
|
if (!deadlockLikely && !gridlockLikely)
|
||||||
{ return; }
|
{ return; }
|
||||||
|
|||||||
+7
-7
@@ -27,10 +27,10 @@ void PuppetComponent::defaultPuppetMain(
|
|||||||
if (args.preJoltHook) { args.preJoltHook(thr); }
|
if (args.preJoltHook) { args.preJoltHook(thr); }
|
||||||
|
|
||||||
/** FIXME:
|
/** FIXME:
|
||||||
* Figure out why we don't call reset() here, and then explicitly document
|
* Figure out why we don't call restart() here, and then explicitly document
|
||||||
* it.
|
* it.
|
||||||
*/
|
*/
|
||||||
thr.getIoService().run();
|
thr.getIoContext().run();
|
||||||
thr.initializeTls();
|
thr.initializeTls();
|
||||||
|
|
||||||
comp.postJoltHook();
|
comp.postJoltHook();
|
||||||
@@ -52,15 +52,15 @@ void PuppetComponent::defaultPuppetMain(
|
|||||||
/** EXPLANATION:
|
/** EXPLANATION:
|
||||||
* This reset() call is crucial for async bridging patterns
|
* This reset() call is crucial for async bridging patterns
|
||||||
* to work.
|
* to work.
|
||||||
* When the outermost thread's io_service is stop()ped (e.g.,
|
* When the outermost thread's io_context is stop()ped (e.g.,
|
||||||
* from JOLT sequence), it won't process any new work until
|
* from JOLT sequence), it won't process any new work until
|
||||||
* reset() is called, even if nested async operations try to
|
* restart() is called, even if nested async operations try to
|
||||||
* post work to it. This means async bridges invoked from
|
* post work to it. This means async bridges invoked from
|
||||||
* the outermost thread main sequence won't work until this
|
* the outermost thread main sequence won't work until this
|
||||||
* reset() call.
|
* restart() call.
|
||||||
*/
|
*/
|
||||||
thr.getIoService().reset();
|
thr.getIoContext().restart();
|
||||||
thr.getIoService().run();
|
thr.getIoContext().run();
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|||||||
+16
-16
@@ -4,7 +4,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#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>
|
||||||
@@ -49,7 +49,7 @@ std::shared_ptr<PuppeteerThread> ComponentThread::getPptr()
|
|||||||
void PuppeteerThread::exitLoop(void)
|
void PuppeteerThread::exitLoop(void)
|
||||||
{
|
{
|
||||||
keepLooping = false;
|
keepLooping = false;
|
||||||
getIoService().stop();
|
getIoContext().stop();
|
||||||
std::cout << name << ": Signaled main loop to exit." << "\n";
|
std::cout << name << ": Signaled main loop to exit." << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ public:
|
|||||||
"JOLT request."
|
"JOLT request."
|
||||||
<< "\n";
|
<< "\n";
|
||||||
|
|
||||||
target->io_service.stop();
|
target->io_context.stop();
|
||||||
callOriginalCb();
|
callOriginalCb();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ public:
|
|||||||
"exitThread (main queue)." << "\n";
|
"exitThread (main queue)." << "\n";
|
||||||
|
|
||||||
target->cleanup();
|
target->cleanup();
|
||||||
target->io_service.stop();
|
target->io_context.stop();
|
||||||
callOriginalCb();
|
callOriginalCb();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,8 +142,8 @@ public:
|
|||||||
"exitThread (pause queue)."<< "\n";
|
"exitThread (pause queue)."<< "\n";
|
||||||
|
|
||||||
target->cleanup();
|
target->cleanup();
|
||||||
target->pause_io_service.stop();
|
target->pause_io_context.stop();
|
||||||
target->io_service.stop();
|
target->io_context.stop();
|
||||||
callOriginalCb();
|
callOriginalCb();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,8 +159,8 @@ public:
|
|||||||
* have a chance to invoke the callback until it's unblocked.
|
* have a chance to invoke the callback until it's unblocked.
|
||||||
*/
|
*/
|
||||||
callOriginalCb();
|
callOriginalCb();
|
||||||
target->pause_io_service.reset();
|
target->pause_io_context.restart();
|
||||||
target->pause_io_service.run();
|
target->pause_io_context.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
void resumeThreadReq1_posted(
|
void resumeThreadReq1_posted(
|
||||||
@@ -170,7 +170,7 @@ public:
|
|||||||
std::cout << __func__ << ": Thread '" << target->name << "': handling "
|
std::cout << __func__ << ": Thread '" << target->name << "': handling "
|
||||||
"resumeThread." << "\n";
|
"resumeThread." << "\n";
|
||||||
|
|
||||||
target->pause_io_service.stop();
|
target->pause_io_context.stop();
|
||||||
callOriginalCb();
|
callOriginalCb();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -210,7 +210,7 @@ void PuppetThread::joltThreadReq(
|
|||||||
auto request = std::make_shared<ThreadLifetimeMgmtOp>(
|
auto request = std::make_shared<ThreadLifetimeMgmtOp>(
|
||||||
puppeteer, selfPtr, callback);
|
puppeteer, selfPtr, callback);
|
||||||
|
|
||||||
this->getIoService().post(
|
boost::asio::post(this->getIoContext(),
|
||||||
STC(std::bind(
|
STC(std::bind(
|
||||||
&ThreadLifetimeMgmtOp::joltThreadReq1_posted,
|
&ThreadLifetimeMgmtOp::joltThreadReq1_posted,
|
||||||
request.get(), request)));
|
request.get(), request)));
|
||||||
@@ -224,7 +224,7 @@ void PuppetThread::startThreadReq(cps::Callback<threadLifetimeMgmtOpCbFn> callba
|
|||||||
caller, std::static_pointer_cast<PuppetThread>(shared_from_this()),
|
caller, std::static_pointer_cast<PuppetThread>(shared_from_this()),
|
||||||
callback);
|
callback);
|
||||||
|
|
||||||
this->getIoService().post(
|
boost::asio::post(this->getIoContext(),
|
||||||
STC(std::bind(
|
STC(std::bind(
|
||||||
&ThreadLifetimeMgmtOp::startThreadReq1_posted,
|
&ThreadLifetimeMgmtOp::startThreadReq1_posted,
|
||||||
request.get(), request)));
|
request.get(), request)));
|
||||||
@@ -237,12 +237,12 @@ void PuppetThread::exitThreadReq(cps::Callback<threadLifetimeMgmtOpCbFn> callbac
|
|||||||
caller, std::static_pointer_cast<PuppetThread>(shared_from_this()),
|
caller, std::static_pointer_cast<PuppetThread>(shared_from_this()),
|
||||||
callback);
|
callback);
|
||||||
|
|
||||||
this->getIoService().post(
|
boost::asio::post(this->getIoContext(),
|
||||||
STC(std::bind(
|
STC(std::bind(
|
||||||
&ThreadLifetimeMgmtOp::exitThreadReq1_mainQueue_posted,
|
&ThreadLifetimeMgmtOp::exitThreadReq1_mainQueue_posted,
|
||||||
request.get(), request)));
|
request.get(), request)));
|
||||||
|
|
||||||
pause_io_service.post(
|
boost::asio::post(pause_io_context,
|
||||||
STC(std::bind(
|
STC(std::bind(
|
||||||
&ThreadLifetimeMgmtOp::exitThreadReq1_pauseQueue_posted,
|
&ThreadLifetimeMgmtOp::exitThreadReq1_pauseQueue_posted,
|
||||||
request.get(), request)));
|
request.get(), request)));
|
||||||
@@ -261,7 +261,7 @@ void PuppetThread::pauseThreadReq(cps::Callback<threadLifetimeMgmtOpCbFn> callba
|
|||||||
caller, std::static_pointer_cast<PuppetThread>(shared_from_this()),
|
caller, std::static_pointer_cast<PuppetThread>(shared_from_this()),
|
||||||
callback);
|
callback);
|
||||||
|
|
||||||
this->getIoService().post(
|
boost::asio::post(this->getIoContext(),
|
||||||
STC(std::bind(
|
STC(std::bind(
|
||||||
&ThreadLifetimeMgmtOp::pauseThreadReq1_posted,
|
&ThreadLifetimeMgmtOp::pauseThreadReq1_posted,
|
||||||
request.get(), request)));
|
request.get(), request)));
|
||||||
@@ -275,13 +275,13 @@ void PuppetThread::resumeThreadReq(cps::Callback<threadLifetimeMgmtOpCbFn> callb
|
|||||||
+ ": invoked on puppeteer thread");
|
+ ": invoked on puppeteer thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post to the pause_io_service to unblock the paused thread
|
// Post to the pause_io_context to unblock the paused thread
|
||||||
std::shared_ptr<ComponentThread> caller = getSelf();
|
std::shared_ptr<ComponentThread> caller = getSelf();
|
||||||
auto request = std::make_shared<ThreadLifetimeMgmtOp>(
|
auto request = std::make_shared<ThreadLifetimeMgmtOp>(
|
||||||
caller, std::static_pointer_cast<PuppetThread>(shared_from_this()),
|
caller, std::static_pointer_cast<PuppetThread>(shared_from_this()),
|
||||||
callback);
|
callback);
|
||||||
|
|
||||||
pause_io_service.post(
|
boost::asio::post(pause_io_context,
|
||||||
STC(std::bind(
|
STC(std::bind(
|
||||||
&ThreadLifetimeMgmtOp::resumeThreadReq1_posted,
|
&ThreadLifetimeMgmtOp::resumeThreadReq1_posted,
|
||||||
request.get(), request)));
|
request.get(), request)));
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ void PuppeteerComponent::defaultPuppeteerMain(
|
|||||||
|
|
||||||
if (args.preJoltHook) { args.preJoltHook(thr); }
|
if (args.preJoltHook) { args.preJoltHook(thr); }
|
||||||
|
|
||||||
thr.getIoService().reset();
|
thr.getIoContext().restart();
|
||||||
thr.getIoService().run();
|
thr.getIoContext().run();
|
||||||
thr.initializeTls();
|
thr.initializeTls();
|
||||||
|
|
||||||
comp.postJoltHook();
|
comp.postJoltHook();
|
||||||
@@ -40,17 +40,17 @@ void PuppeteerComponent::defaultPuppeteerMain(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
/** EXPLANATION:
|
/** EXPLANATION:
|
||||||
* This reset() call is crucial for async bridging
|
* This restart() call is crucial for async bridging
|
||||||
* patterns to work.
|
* patterns to work.
|
||||||
* When the outermost thread's io_service is stop()ped
|
* When the outermost thread's io_context is stop()ped
|
||||||
* (e.g., from JOLT sequence), it won't process any new
|
* (e.g., from JOLT sequence), it won't process any new
|
||||||
* work until reset() is called, even if nested async
|
* work until restart() is called, even if nested async
|
||||||
* operations try to post work to it. This means async
|
* operations try to post work to it. This means async
|
||||||
* bridges invoked from the outermost thread main sequence
|
* bridges invoked from the outermost thread main sequence
|
||||||
* won't work until this reset() call.
|
* won't work until this restart() call.
|
||||||
*/
|
*/
|
||||||
thr.getIoService().reset();
|
thr.getIoContext().restart();
|
||||||
thr.getIoService().run();
|
thr.getIoContext().run();
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|||||||
+3
-3
@@ -288,8 +288,8 @@ void Qutex::backoff(
|
|||||||
* (Assume that Lv2 was not at the front of the common qutex's
|
* (Assume that Lv2 was not at the front of the common qutex's
|
||||||
* internal queue -- it only needed to be in the top 66%.)
|
* internal queue -- it only needed to be in the top 66%.)
|
||||||
* Lv1 tries to acquire the common lock and fails. It gets taken off of
|
* Lv1 tries to acquire the common lock and fails. It gets taken off of
|
||||||
* its io_service. It's now asleep until it gets
|
* its io_context. It's now asleep until it gets
|
||||||
* re-added into an io_service.
|
* re-added into an io_context.
|
||||||
* Lv2 fails to acquire the other 2 locks it needs and backoff()s from
|
* Lv2 fails to acquire the other 2 locks it needs and backoff()s from
|
||||||
* the common lock it shares with Lv1.
|
* the common lock it shares with Lv1.
|
||||||
*
|
*
|
||||||
@@ -357,7 +357,7 @@ void Qutex::release()
|
|||||||
* Just before Lv1 can acquire the common lock, Lv2 acquires it now,
|
* Just before Lv1 can acquire the common lock, Lv2 acquires it now,
|
||||||
* because it only needs to be in the top 66% to succeed.
|
* because it only needs to be in the top 66% to succeed.
|
||||||
* Lv1 checks the currOwner and sees that it's owned. Lv1 is now
|
* Lv1 checks the currOwner and sees that it's owned. Lv1 is now
|
||||||
* dequeued from its io_service. It won't be awakened until someone
|
* dequeued from its io_context. It won't be awakened until someone
|
||||||
* awakens it.
|
* awakens it.
|
||||||
* Lv2 finishes its critical section and releas()es the common lock.
|
* Lv2 finishes its critical section and releas()es the common lock.
|
||||||
* Lv2 was not at the front of the qutexQ, so it does NOT awaken the
|
* Lv2 was not at the front of the qutexQ, so it does NOT awaken the
|
||||||
|
|||||||
Reference in New Issue
Block a user