[#cobalt_operation] == cobalt/op.hpp An operation in `cobalt` is an <> wrapping an `asio` operation. [#use_op] === use_op The `use_op` token is the direct to create an op, i.e. using `cobalt::use_op` as the completion token will create the required awaitable. [source,cpp] ---- auto tim = cobalt::use_op.as_default_on(asio::steady_timer{co_await cobalt::this_coro::executor}); co_await tim.async_wait(); ---- Depending on the completion signature the `co_await` expression may throw. [cols="1,1,1"] |=== | Signature | Return type | Exception | `void()` | `void` | `noexcept` | `void(T)` | `T` | `noexcept` | `void(T...)` | `std::tuple` | `noexcept` | `void(system::error_code, T)` | `T` | `system::system_error` | `void(system::error_code, T...)` | `std::tuple` | `system::system_error` | `void(std::exception_ptr, T)` | `T` | _any exception_ | `void(std::exception_ptr, T...)` | `std::tuple` | _any exception_ |=== NOTE: `use_op` will never complete immediately, i.e. `await_ready` will always return false, but always suspend the coroutine. [#op] === Hand coded Operations Operations are a more advanced implementation of the <> feature. This library makes it easy to create asynchronous operations with an early completion condition, i.e. a condition that avoids suspension of coroutines altogether. We can for example create a `wait_op` that does nothing if the timer is already expired. [source,cpp] ---- struct wait_op : cobalt::op // <1> { asio::steady_timer & tim; wait_op(asio::steady_timer & tim) : tim(tim) {} bool ready(cobalt::handler ) // <2> { if (tim.expiry() < std::chrono::steady_clock::now()) h(system::error_code{}); } void initiate(cobalt::completion_handler complete) // <3> { tim.async_wait(std::move(complete)); } }; ---- <1> Inherit `op` with the matching signature `await_transform` picks it up <2> Check if the operation is ready - called from `await_ready` <3> Initiate the operation if its not ready.