.. _ex_braid:

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 :literal_ref:`tmc::post()<post>` / :literal_ref:`tmc::post_bulk()<post_bulk>`.
If a task is already running on a braid, ``co_await`` ing or :literal_ref:`spawn()<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 :literal_ref:`tmc::enter()<aw_enter_exit>` / :literal_ref:`tmc::exit()<aw_enter_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.

.. code-block:: cpp

  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 :literal_ref:`run_on()<run_on>`, after which the parent task will resume back on the original executor.

.. code-block:: cpp

  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
-----------------------------------------------------------------------------------
.. _ex_braid_class:

.. doxygenclass:: tmc::ex_braid
   :members:
