Integrating External Executors#
Setting the Default Executor#
When tmc::spawn*()
is called, the work is typically submitted to the current thread’s executor (tmc::detail::this_thread::executor
).
If the current thread is an external thread, it won’t be configured with an executor.
You can set a default executor which will be used as a fallback in this situation.
You only need to call tmc::set_default_executor()
once to enable this globally.
-
inline void tmc::set_default_executor(tmc::ex_any *Executor)#
You only need to set this if you are planning to integrate TMC with external threads of execution that don’t configure
tmc::detail::this_thread::executor
.If a TMC function that submits work to the current executor implicitly, such as
spawn()
, is invoked:on a non-TMC thread that has not set
tmc::detail::this_thread::executor
without explicitly specifying an executor via
.run_on()
/.resume_on()
then that function will use this default executor (instead of deferencing nullptr and crashing).
-
template<typename Exec>
inline void tmc::set_default_executor(Exec &Executor)# You only need to set this if you are planning to integrate TMC with external threads of execution that don’t configure
tmc::detail::this_thread::executor
.If a TMC function that submits work to the current executor implicitly, such as
spawn()
, is invoked:on a non-TMC thread that has not set
tmc::detail::this_thread::executor
without explicitly specifying an executor via
.run_on()
/.resume_on()
then that function will use this default executor (instead of deferencing nullptr and crashing).
-
template<typename Exec>
inline void tmc::set_default_executor(Exec *Executor)# You only need to set this if you are planning to integrate TMC with external threads of execution that don’t configure
tmc::detail::this_thread::executor
.If a TMC function that submits work to the current executor implicitly, such as
spawn()
, is invoked:on a non-TMC thread that has not set
tmc::detail::this_thread::executor
without explicitly specifying an executor via
.run_on()
/.resume_on()
then that function will use this default executor (instead of deferencing nullptr and crashing).
Fully Integrating#
External libraries or users may provide a type that fully satisfies the concept of an “executor” by
implementing a specialization of the tmc::detail::executor_traits
struct.
Additionally, they must implement the following behaviors:
Threads that participate in the executor should set the value of
tmc::detail::this_thread::executor
.
If all threads of execution implement this behavior, then tmc::external::set_default_executor()
is not necessary.
The members of the tmc::detail::executor_traits
struct are described below.
Also see the docs for tmc::work_item
.
template <> struct tmc::detail::executor_traits<your_executor> {
static void post(your_executor& ex, tmc::work_item&& Item, size_t Priority);
// Iter will be a forward iterator of tmc::work_item.
template <typename Iter>
static void post_bulk(your_executor& ex, Iter&& Items, size_t Count, size_t Priority);
static tmc::ex_any* type_erased(your_executor& ex);
static std::coroutine_handle<> task_enter_context(
your_executor& ex, std::coroutine_handle<> Outer, size_t Priority
);
};
Example Implementation#
A complete, minimal implementation of tmc::detail::executor_traits
is available in the external_executor example.