tmc::ex_braid#

ex_braid is a serializing executor. Only one thread can run tasks on the ex_braid at a time.

An instance of ex_braid must be created as a child of another executor; threads from the parent executor will participate in executing tasks on the ex_braid.

You can submit work items to a braid like any other executor using tmc::post() / tmc::post_bulk(). If a task is already running on a braid, co_await ing or spawn() ing tasks will also execute those tasks in the braid.

Usage Example#

You can enter a braid in the middle of a coroutine using tmc::enter() / tmc::exit() . In this way, a braid can be used as a fine-grained lock or async mutex. Entering and exiting a braid has acquire/release semantics.

int non_atomic_counter;

tmc::task<void> braid_lock_middle(tmc::ex_braid& braid) {
  // assume we start on the cpu executor here
  int my_count;

  auto lock = co_await tmc::enter(braid);
  // we are on the braid now;
  // accessing non_atomic_counter inside this block is thread-safe
  my_count = non_atomic_counter;
  non_atomic_counter++;
  co_await lock.exit();

  // we are back on the cpu executor now, with our original priority
}

You can run a child task on the braid using run_on(), after which the parent task will resume back on the original executor.

int non_atomic_counter;

tmc::task<int> next_count() {
  return non_atomic_counter++;
}

tmc::task<void> braid_lock_child(tmc::ex_braid& braid) {
  // assume we start on the cpu executor here

  // only the child task will run on the braid, where it can safely access non_atomic_counter
  int my_count = co_await tmc::spawn(next_count()).run_on(braid);

  // we are still on the cpu executor afterward
}

API Reference#

class ex_braid#

Public Functions

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

Submits a single work_item to the braid, and attempts to take the lock and start executing tasks on the braid.

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

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 braid, and attempts to take the lock and start executing tasks on the braid. It must be an iterator type that implements operator*() and It& operator++().

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

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

ex_braid()#

Construct a braid with the current executor as its parent. It is an error to call this from a thread that is not running on an executor.

template<typename Executor>
inline ex_braid(Executor &Parent)#

Construct a braid with the specified executor as its parent.