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. 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().

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.