tmc::ex_cpu_st#

ex_cpu_st is a single-threaded executor. It behaves the same as an ex_cpu with .set_thread_count(1). However, it has better round-trip latency and better internal execution performance, as it does not need the thread tracking and synchronization systems that are present in the multi-threaded executor.

This single-threaded executor may be useful to manage communication with certain systems that require all calls to come from the same thread (e.g. SDL/OpenGL).

You must call .init() on each executor instance before you use it. Before calling init(), you may configure it by calling any of the member functions that begin with set_.

Usage Example#

#define TMC_IMPL
#include "tmc/all_headers.hpp"

int main() {
  // Run async_main on the global (multi-threaded) ex_cpu
  tmc::cpu_executor().init();
  return tmc::async_main([]() -> tmc::task<int> {

    // Configure and run a single-threaded executor
    tmc::ex_cpu_st single_threaded_exec;
    single_threaded_exec.init();

    // This child task will be executed on single_threaded_exec
    co_await tmc::spawn(some_task()).run_on(single_threaded_exec);
    // After it completes, the main task will resume back on the global ex_cpu

    co_return 0;
  }());
}

API Reference#

class ex_cpu_st#

A single-threaded executor. Behaves the same as ex_cpu with .set_thread_count(1), but with better round-trip latency, and better internal execution performance, as it does not need internal synchronization mechanisms.

Public Functions

ex_cpu_st &add_partition(tmc::topology::topology_filter Filter)#

Requires TMC_USE_HWLOC. Builder func to limit the executor to a subset of the available CPUs. This should only be called once, as this is a single-threaded executor.

ex_cpu_st &set_priority_count(size_t PriorityCount)#

Builder func to set the number of priority levels before calling init(). The value must be in the range [1, 16]. The default is 1.

size_t priority_count()#

Gets the number of priority levels. Only useful after init() has been called.

size_t thread_count()#

Gets the number of worker threads. Always returns 1.

ex_cpu_st &set_thread_init_hook(std::function<void(size_t)> Hook)#

Builder func to set a hook that will be invoked at the startup of the executor thread, and passed the ordinal index of the thread (which is always 0, since this is a single-threaded executor).

ex_cpu_st &set_thread_teardown_hook(std::function<void(size_t)> Hook)#

Builder func to set a hook that will be invoked before destruction of each thread owned by this executor, and passed the ordinal index of the thread (which is always 0, since this is a single-threaded executor).

ex_cpu_st &set_spins(size_t Spins)#

Builder func to set the number of times that a thread worker will spin looking for new work when all queues appear to be empty before suspending the thread. Each spin is an asm(“pause”) followed by re-checking all queues. The default is 4.

void init()#

Initializes the executor. If you want to customize the behavior, call the set_X() functions before calling init().

If the executor is already initialized, calling init() will do nothing.

void teardown()#

Stops the executor, joins the worker thread, and destroys resources. Does not wait for any queued work to complete. teardown() must not be called from this executor’s thread.

Restores the executor to an uninitialized state. After calling teardown(), you may call set_X() to reconfigure the executor and call init() again.

If the executor is not initialized, calling teardown() will do nothing.

ex_cpu_st()#

After constructing, you must call init() before use.

~ex_cpu_st()#

Invokes teardown(). Must not be called from this executor’s thread.

void post(work_item &&Item, size_t Priority = 0, size_t ThreadHint = NO_HINT)#

Submits a single work_item to the executor. If Priority is out of range, it will be clamped to an in-range value.

Rather than calling this directly, it is recommended to use the tmc::post() free function template.

tmc::ex_any *type_erased()#

Returns a pointer to the type erased ex_any version of this executor. This object shares a lifetime with this executor, and can be used for pointer-based equality comparison against the thread-local tmc::current_executor().

template<typename It>
inline void post_bulk(It &&Items, size_t Count, size_t Priority = 0, size_t ThreadHint = NO_HINT)#

Submits count items to the executor. It is expected to be an iterator type that implements operator*() and It& operator++(). If Priority is out of range, it will be clamped to an in-range value.

Rather than calling this directly, it is recommended to use the tmc::post_bulk() free function template.