Coroutines

Cancellable, co_await-able tasks and lazily produced value sequences. More...

Classes

class  AwaiterBase
 Defines the cancellation interface for a pending awaitable. More...
class  Awaiter
 Provides the base class for I/O-driven co_await-able operations. More...
class  BasicAwaiter< R >
 Provides an awaitable that delivers a result through onReady(). More...
class  BasicAwaiter< void >
 Specializes BasicAwaiter for awaitables without a result. More...
class  Task< T >
 Represents a cancellable C++20 coroutine that produces a single result. More...
class  Generator< T >
 Represents a coroutine that yields a sequence of values and may itself co_await. More...
class  Generator< T >::NextAwaiter
 Provides the awaitable returned by Generator::next(). More...

Detailed Description

A Task is a C++20 coroutine that produces a single result and can be cancelled while it is suspended. A Generator yields a sequence of values and may also suspend. Both types integrate with the event loop: awaitable operations resume the coroutine when I/O, timers or other loop-driven work complete.

These types are available when the program is compiled as C++20 or later.

Use a function that returns Task as an asynchronous unit of work. The coroutine starts suspended. Use Task::run() to begin execution on the current thread. After the task has finished, Task::done() is true and Task::result() returns the value.

Inside a task, co_await suspends until an awaitable operation completes. Framework types already provide awaitables, for example Pt::System::Timer::waitAsync() for a one-shot delay. Custom operations derive from Awaiter or BasicAwaiter.

I/O awaitables typically resume from the event loop. The usual pairing is to start the task with Task::run() and then run the loop so completions can resume the coroutine.

Destroying a task or calling Task::cancel() aborts the pending awaitable and destroys the coroutine frame. Nested tasks cancel the inner pending operation the same way. A generator cancels in the same manner.

Exceptions that leave a coroutine body are stored. They are rethrown by Task::result() and by co_await of that task.

The following example starts a task that waits for a timer and then exits the loop:

Pt::Task<> delayThenExit(Pt::System::EventLoop& loop,
{
co_await timer.waitAsync(1000);
loop.exit();
}
int main()
{
timer.setActive(loop);
Pt::Task<> task = delayThenExit(loop, timer);
task.run();
return loop.run();
}
Event loop of a thread or process.
Definition EventLoop.h:83
void run()
Starts the loop.
void exit()
Stops the loop.
Platform event loop.
Definition MainLoop.h:51
Interval timeout notifications.
Definition Timer.h:74
void setActive(EventLoop &loop)
Sets the used event loop.
AsyncWait waitAsync(std::size_t ms)
Start a one-shot timer delay as a C++20 awaitable.
Represents a cancellable C++20 coroutine that produces a single result.
Definition Coroutine.h:436
void run()
Starts execution of the coroutine.
Definition Coroutine.h:518