wwa-coro 0.0.1
Yet Another C++20 Coroutine Library
|
This project provides a set of coroutine-based asynchronous utilities and generators for C++20. It includes synchronous and asynchronous generators, tasks, and various utilities to facilitate coroutine-based programming.
Option | Description | Default |
---|---|---|
BUILD_TESTS | Build tests | ON |
BUILD_EXAMPLES | Build examples | ON |
BUILD_DOCS | Build documentation | ON |
BUILD_INTERNAL_DOCS | Build internal documentation | OFF |
ENABLE_MAINTAINER_MODE | Maintainer mode (enable more compiler warnings, treat warnings as errors) | OFF |
USE_CLANG_TIDY | Use clang-tidy during build | OFF |
The BUILD_DOCS
(public API documentation) and BUILD_INTERNAL_DOCS
(public and private API documentation) require Doxygen and, optionally, dot
(a part of Graphviz).
The USE_CLANG_TIDY
option requires clang-tidy
.
Build Type | Description |
---|---|
Debug | Build with debugging information and no optimization. |
Release | Build with optimization for maximum performance and no debugging information. |
RelWithDebInfo | Build with optimization and include debugging information. |
MinSizeRel | Build with optimization for minimum size. |
ASAN | Build with AddressSanitizer enabled for detecting memory errors. |
LSAN | Build with LeakSanitizer enabled for detecting memory leaks. |
UBSAN | Build with UndefinedBehaviorSanitizer enabled for detecting undefined behavior. |
TSAN | Build with ThreadSanitizer enabled for detecting data races. |
Coverage | Build with code coverage analysis enabled. |
ASAN, LSAN, UBSAN, TSAN, and Coverage builds are only supported with GCC or clang.
Coverage build requires gcov
(GCC) or llvm-gcov
(clang) and gcovr
.
To run the tests, use the following command:
or run the following binary:
The test binary uses Google Test library. Its behavior can be controlled via environment variables and/or command line flags.
Run coro_test --help
for the list of available options.
The documentation is available at https://sjinks.github.io/coro-cpp/.
eager_task
)An eager coroutine start execution immediately upon creation and does not suspend upon completion. From the caller's perspective, it runs synchoronously; the control is returned to the caller only after the coroutine finishes.
Eager coroutines can co_await
other coroutines but they cannot be co_await
'ed.
task<T>
)Tasks are lightweight coroutines that start executing when they are awaited; they can optionally return values (the type of the return value is determined by the template parameter T
). Use tasks to create your coroutines, and use co_await
or co_yield
within tasks to perform asynchronous operations.
It is possible to turn any task (or any awaitable) into a fire-anf-forget eager coroutine. For the example above,
See examples/task.cpp.
generator<T>
)Generators are special coroutines that produce sequences of values of a specified type (T
). These values are produced lazily and synchronously.
The coroutine body is able to yield values of type T
using the co_yield
keyword. However, the coroutine body is not able to use the co_await
keyword; values must be produced synchronously.
Generators can be used with range-based for
loops and ranges.
async_generator<T>
)Generators are special coroutines that produce sequences of values of a specified type (T
). These values are produced lazily and asynchronously.
Unlike the synchronous counterpart, the coroutine body is able to use both co_await
and co_yield
expressions.
See examples/async_generator.cpp.
Unfortunately, it is impossible to use asynchronous iterators directly in range-based for
loops. However, this limitation can be overcome with the help of eager coroutines.
There is a helper adapter, sync_generator_adapter<T>
, that turns an asynchronous generator into a quasi-synchronous one: