Coroutines / tmc::task#

TMC’s coroutine type is tmc::task<Result>. It is a lazy/cold coroutine, and will not start executing until it is co_await ed, submitted to an executor, or manually resumed.

It is a work item, so it is compatible with the tmc::post*() family of functions.

It is an awaitable, so it is compatible with the tmc::spawn*() family of functions.

Task is a linear type. It must be passed around by move, and then ultimately awaited exactly once.

  • It cannot be copied.

  • It must be moved into any operation that uses it. This includes:

    • co_await

    • post*()

    • spawn*()

  • A moved-from task must not be used afterward.

  • It will destroy its associated coroutine frame/promise after it completes.

  • The result that it produces will be available in the awaiting coroutine’s scope.

  • It cannot be co_awaited again to produce the same result again.

API Reference#

template<typename Result>
struct task#

The main coroutine type used by TooManyCooks. task is a lazy / cold coroutine and will not begin running immediately. To start running a task, you can:

Use co_await directly on the task to run it and await the results.

Call tmc::spawn() to create a task wrapper that can be configured before co_await ing the results.

Call tmc::spawn_many() to submit and await multiple tasks at once. This task group can be configured before co_await ing the results.

Call tmc::post() / tmc::post_waitable() to submit this task for execution to an async executor from external (non-async) calling code.

Public Functions

inline aw_task<task<Result>, Result> operator co_await() && noexcept#

Suspend the outer coroutine and run this task directly. The intermediate awaitable type aw_task cannot be used directly; the return type of the co_await expression will be Result or void.

inline task &resume_on(tmc::ex_any *Executor) & noexcept#

When this task completes, the awaiting coroutine will be resumed on the provided executor.

template<typename Exec>
inline task &resume_on(Exec &Executor) & noexcept#

When this task completes, the awaiting coroutine will be resumed on the provided executor.

template<typename Exec>
inline task &resume_on(Exec *Executor) & noexcept#

When this task completes, the awaiting coroutine will be resumed on the provided executor.

inline task &&resume_on(tmc::ex_any *Executor) && noexcept#

When this task completes, the awaiting coroutine will be resumed on the provided executor.

template<typename Exec>
inline task &&resume_on(Exec &Executor) && noexcept#

When this task completes, the awaiting coroutine will be resumed on the provided executor.

template<typename Exec>
inline task &&resume_on(Exec *Executor) && noexcept#

When this task completes, the awaiting coroutine will be resumed on the provided executor.

inline task(std::coroutine_handle<promise_type> &&Other) noexcept#

Tasks are move-only.

task(const task &other) = delete#

Non-copyable.

inline ~task()#

When this task is destroyed, it should already have been deinitialized. Either because it was moved-from, or because the coroutine completed.

inline operator std::coroutine_handle<>() && noexcept#

Conversion to a std::coroutine_handle<> is move-only.

inline operator std::coroutine_handle<promise_type>() && noexcept#

Conversion to a std::coroutine_handle<> is move-only.