### Getting Started with co_main Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates the basic usage of the `co_main` function in Cobalt, which simplifies setting up an asynchronous application by providing an event loop and handling coroutine execution. ```cpp cobalt::main co_main(int argc, char *argv[]) { auto exec = co_await cobalt::this_coro::executor; asio::steady_timer tim{exec, std::chrono::milliseconds(50)}; co_await tim.async_wait(cobalt::use_op); co_return 0; } ``` -------------------------------- ### Promise-Based Coroutine Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates the usage of `cobalt::promise` for creating eager coroutines. This example shows how to initiate a promise, perform other operations, and then await its result. ```cpp cobalt::promise my_promise() { co_await do_the_thing(); co_return 0; } cobalt::main co_main(int argc, char * argv[]) { // start the promise here auto p = my_promise(); // do something else here co_await do_the_other_thing(); // wait for the promise to complete auto res = co_await p; co_return res; } ``` -------------------------------- ### Endpoint Construction Example (C++) Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Demonstrates how to construct an `endpoint` object using `cobalt::io::tcp_v4`, an IP address, and a port number. This example showcases a common use case for creating network endpoints. ```cpp cobalt::io::endpoint ep{cobalt::io::tcp_v4, "127.0.0.1", 8080}; ``` -------------------------------- ### Create Cobalt TCPv4 endpoint example (C++) Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates the creation of a Cobalt endpoint for a TCPv4 protocol. This example shows how to instantiate an `endpoint` object with specific network details like the IP address and port number. ```cpp cobalt::io::endpoint ep{cobalt::io::tcp_v4, "127.0.0.1", 8080}; ``` -------------------------------- ### Signal Set Wait Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index An example demonstrating how to use the signal_set to wait for specific signals (e.g., SIGINT, SIGTERM) and react to them. It shows asynchronous waiting and conditional execution based on the received signal. ```cpp io::signal_set s = {SIGINT, SIGTERM}; int sig = co_await s.wait(); if (s == SIGINT) interrupt(); else if (s == SIGTERM) terminate(); ``` -------------------------------- ### Coroutine Awaitable Example using `co_await` Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Demonstrates the basic usage of `co_await` with an awaitable expression within a coroutine. This example shows a simple delay operation. ```cpp co_await delay(50ms); ``` -------------------------------- ### Cobalt Promise Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Illustrates the use of `cobalt::promise` for creating eager coroutines that can `co_await` and `co_return` values. This example shows a `delay` function and its usage within `co_main`. ```cpp cobalt::promise delay(std::chrono::milliseconds ms) { asio::steady_timer tim{co_await cobalt::this_coro::executor, ms}; co_await tim.async_wait(cobalt::use_op); } cobalt::main co_main(int argc, char *argv[]) { co_await delay(std::chrono::milliseconds(50)); co_return 0; } ``` -------------------------------- ### Task-Based Coroutine Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Illustrates the use of `cobalt::task` for creating lazy coroutines. This example shows how to define a task, perform other operations, and then await its result. ```cpp cobalt::task my_task() { co_await do_the_thing(); co_return 0; } cobalt::main co_main(int argc, char * argv[]) { // create the task here auto t = my_task(); // do something else here first co_await do_the_other_thing(); // start and wait for the task to complete auto res = co_await t; co_return res; } ``` -------------------------------- ### Coroutine Entry: cobalt::task and asio (C++) Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Illustrates running coroutines using `cobalt::task` and integrating with `asio::io_context`. This example shows both synchronous execution with `cobalt::run` and asynchronous spawning with `asio::spawn` and `ctx.run()`. ```cpp cobalt::task my_thread() { // co_await things here co_return; } int main(int argc, char ** argv[]) { cobalt::run(my_task()); // sync asio::io_context ctx; cobalt::spawn(ctx, my_task(), asio::detached); ctx.run(); return 0; } ``` -------------------------------- ### C++: Example of reusing and awaiting a write_op Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates how to reuse and await a `write_op` object. The example shows obtaining a `write_op`, awaiting its completion, and then continuing to await it in a loop as long as data is being written, modifying the buffer member between awaits. ```cpp write_op wo = do_w; auto sz = co_await wo; while (sz > 0) { wo.buffer += sz; sz = co_await wo; } ``` -------------------------------- ### Query, Require, and Prefer Executor Properties in C++ Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates how to implement query, require, and prefer methods for executor properties. The query method retrieves current property values, require ensures an executor has specific properties, and prefer optionally adds properties. This example shows relationship property handling. ```cpp struct example_executor { // get a property by querying it. asio::execution::relationship_t &query(asio::execution::relationship_t) const { return asio::execution::relationship.fork; } // require an executor with a new property never_blocking_executor require(const execution::blocking_t::never_t); // prefer an executor with a new property. the executor may or may not support it. never_blocking_executor prefer(const execution::blocking_t::never_t); // not supported example_executor prefer(const execution::blocking_t::always_t); }; ``` -------------------------------- ### C++: Channel Reading with BOOST_COBALT_FOR Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Illustrates using `BOOST_COBALT_FOR` with `cobalt::channel_reader` in C++ for a more convenient way to iterate over channel values. This example reads integers from a channel and prints them. ```cpp cobalt::main co_main(int argc, char * argv[]) { cobalt::channel c; auto p = producer(c); // Assuming producer is defined as in the previous example BOOST_COBALT_FOR(int value, cobalt::channel_reader(c)) std::cout << value << std::endl; co_await p; co_return 0; } ``` -------------------------------- ### Cobalt Generator Example: Basic Usage Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates the basic usage of `cobalt::generator` for creating eager coroutines that yield and return values. It shows how to call a generator and sequentially `co_await` its results, illustrating the interleaved execution between the generator and the main function. ```cpp cobalt::generator example() { printf("In coro 1\n"); co_yield 2; printf("In coro 3\n"); co_return 4; } cobalt::main co_main(int argc, char * argv[]) { printf("In main 0\n"); auto f = example(); // call and let it run until the first co_yield printf("In main 1\n"); printf("In main %d\n", co_await f); printf("In main %d\n", co_await f); return 0; } ``` -------------------------------- ### C++: WebSocket Session with Custom Tear-down Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index An example in C++ demonstrating the `with` facility for managing a WebSocket connection. It defines connect, disconnect functions, and a custom tear-down function, then uses `cobalt::with` to manage the session lifecycle. ```cpp using ws_stream = beast::websocket::stream>; cobalt::promise connect(urls::url); // __**(1)** cobalt::promise disconnect(ws_stream &ws); // __**(2)** auto teardown(const boost::cobalt::with_exit_tag & wet , ws_stream & ws, std::exception_ptr e) { return disconnect(ws); } cobalt::promise run_session(ws_stream & ws); cobalt::main co_main(int argc, char * argv[]) { co_await cobalt::with(co_await connect(argv[1]), &run_session, &teardown); co_return 0; } ``` -------------------------------- ### Implement Asynchronous Delay with Cobalt and Asio C++ Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index This C++ code snippet demonstrates a simple asynchronous delay using Cobalt's `co_main` and Asio's `steady_timer`. It takes the delay duration from command-line arguments and uses `cobalt::use_op` to await the timer. The `co_main` function simplifies the setup of the asynchronous environment, including executor management and signal handling for cancellations. ```cpp cobalt::main co_main(int argc, char * argv[]) { asio::steady_timer tim{co_await asio::this_coro::executor, std::chrono::milliseconds(std::stoi(argv[1]))}; co_await tim.async_wait(cobalt::use_op); co_return 0; } ``` -------------------------------- ### Synchronous HTTP GET Request in C++ Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index A basic synchronous HTTP GET function that blocks until the request completes. Demonstrates traditional blocking IO where the program waits for the network response before continuing execution. ```cpp std::string http_get(std:string_view url); int main(int argc, char * argv[]) { auto res = http_get("https://boost.org"); printf("%s", res.c_str()); return 0; } ``` -------------------------------- ### C++ Echo Server Declarations using Boost Cobalt Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Defines namespaces for Boost Cobalt and this coroutine, used in the echo server example. No external dependencies beyond Boost Cobalt itself. ```cpp namespace cobalt = boost::cobalt; namespace this_coro = boost::cobalt::this_coro; ``` -------------------------------- ### C++: Channel Usage Example (Producer-Consumer) Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates a producer-consumer pattern using Cobalt's `channel` in C++. A producer coroutine writes integers to a channel, closes it, and a consumer coroutine reads and prints these integers until the channel is closed. ```cpp cobalt::promise producer(cobalt::channel & chan) { for (int i = 0; i < 4; i++) co_await chan.write(i); chan.close(); } cobalt::main co_main(int argc, char * argv[]) { cobalt::channel c; auto p = producer(c); while (c.is_open()) std::cout << co_await c.read() << std::endl; co_await p; co_return 0; } ``` -------------------------------- ### Function call stack example - C++ Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Illustrates a simple synchronous call stack with main calling foo which calls bar. Demonstrates how function frames are stacked during execution, with bar being the deepest point in the stack. ```cpp int bar() {return 0;} // the deepest point of the stack int foo() {return bar();} int main() { return foo(); } ``` -------------------------------- ### Custom Coroutine with Manual Executor Assignment (Full) Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Shows how to define a coroutine that manually assigns an executor, useful when using strands or needing a specific executor. This example uses `asio::executor_arg_t` to specify the executor. ```cpp cobalt::promise example_with_executor(int some_arg, asio::executor_arg_t, cobalt::executor); ``` -------------------------------- ### C++ Detached Coroutine Print Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Shows a C++ detached coroutine that prints 'Hello world' after a specified delay. `co_main` demonstrates initiating this detached coroutine and then waiting for a short period. Detached coroutines are eager and run in the background without being directly awaited. ```cpp cobalt::detached delayed_print(std::chrono::milliseconds ms) { asio::steady_timer tim{co_await cobalt::this_coro::executor, ms}; co_await tim.async_wait(cobalt::use_op); printf("Hello world\n"); } cobalt::main co_main(int argc, char *argv[]) { delayed_print(); co_return 0; } ``` -------------------------------- ### C++ Detached Coroutine Spawning Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Illustrates how to spawn a detached coroutine in C++. The `my_task()` call initiates the coroutine to run in the background. The `co_main` function then waits for a short duration, demonstrating that the detached coroutine executes independently. ```cpp cobalt::detached my_task(); cobalt::main co_main(int argc, char *argv[]) { my_task(); __**(1)** co_await delay(std::chrono::milliseconds(50)); co_return 0; } ``` -------------------------------- ### Use use_op Token for ASIO Operations in Cobalt Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Illustrates how to use the use_op completion token to wrap ASIO operations as awaitables in Cobalt. The example creates a timer with a steady executor and awaits its completion. The use_op token automatically creates awaitable wrappers for ASIO operations and never completes immediately. ```cpp auto tim = cobalt::use_op.as_default_on(asio::steady_timer{co_await cobalt::this_coro::executor}); co_await tim.async_wait(); ``` -------------------------------- ### C++ Task Coroutine Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Demonstrates the usage of a C++ 'task' coroutine in Cobalt for asynchronous operations. It includes a 'delay' function and a 'co_main' entry point that utilizes 'co_await' and 'co_return'. Tasks are lazy coroutines that support yielding values. ```cpp cobalt::task delay(std::chrono::milliseconds ms) { asio::steady_timer tim{co_await cobalt::this_coro::executor, ms}; co_await tim.async_wait(cobalt::use_op); } cobalt::main co_main(int argc, char *argv[]) { co_await delay(std::chrono::milliseconds(50)); co_return 0; } ``` -------------------------------- ### C++ Task Coroutine Delay Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates a C++ task coroutine that introduces a delay using `asio::steady_timer` and then returns a value. The `co_main` function shows how to initiate this delay and exit gracefully. Tasks are lazy coroutines that support `co_await` and `co_return` but not `co_yield`. ```cpp cobalt::task delay(std::chrono::milliseconds ms) { asio::steady_timer tim{co_await cobalt::this_coro::executor, ms}; co_await tim.async_wait(cobalt::use_op); } cobalt::main co_main(int argc, char *argv[]) { co_await delay(std::chrono::milliseconds(50)); co_return 0; } ``` -------------------------------- ### Cobalt Generator Example: Lazy Initialization Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates creating a lazy `cobalt::generator` by using `co_await cobalt::this_coro::initial`. This makes the generator wait until the first `co_await` to begin execution. The value passed during the initial `co_await` is captured by `co_await cobalt::this_coro::initial` and can be used within the coroutine. ```cpp cobalt::generator example() { int v = co_await cobalt::this_coro::initial; printf("In coro %d\n", v); co_yield 2; printf("In coro %d\n", v); co_return 4; } cobalt::main co_main(int argc, char * argv[]) { printf("In main 0\n"); auto f = example(); // call and let it run until the first co_yield printf("In main 1\n"); // < this is now before the co_await initial printf("In main %d\n", co_await f(1)); printf("In main %d\n", co_await f(3)); return 0; } ``` -------------------------------- ### C++ Main Function to Run Blockchain Connector Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index The main asynchronous function that orchestrates the price ticker's operation. It connects to blockchain.info via SSL/WebSocket, sets up a JSON reader, and uses `cobalt::race` to concurrently handle incoming data from the WebSocket and new subscription requests. Dependencies include Asio, Beast, Cobalt, and JSON parsing libraries. ```cpp cobalt::promise run_blockchain_info(cobalt::channel & subc) try { asio::ssl::context ctx{asio::ssl::context_base::tls_client}; websocket_type ws{co_await connect("blockchain.info", ctx)}; co_await connect_to_blockchain_info(ws); subscription_map subs; std::list unconfirmed; auto rd = json_reader(ws); while (ws.is_open()) { switch (auto msg = co_await cobalt::race(rd, subc.read()); msg.index()) { case 0: if (auto ms = get<0>(msg); ms.at("event") == "rejected") co_await handle_rejections(unconfirmed, subs, ms); else co_await handle_update(unconfirmed, subs, ms, ws); break; case 1: co_await handle_new_subscription( unconfirmed, subs, std::move(get<1>(msg)), ws); break; } } for (auto & [k ,c] : subs) { if (auto ptr = c.lock()) ptr->close(); } } catch(std::exception & e) { ``` -------------------------------- ### Immediate Completion Benchmark with Cobalt Channel Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index This benchmark showcases the immediate completion behavior when using an `asio::experimental::channel` with a size of 1. It demonstrates how sending and receiving operations complete immediately, measuring the performance impact of such scenarios using Cobalt. ```c++ cobalt::task atest() { asio::experimental::channel chan{co_await cobalt::this_coro::executor, 1u}; for (std::size_t i = 0u; i < n; i++) { co_await chan.async_send(system::error_code{}, cobalt::use_op); co_await chan.async_receive(cobalt::use_op); } } ``` -------------------------------- ### Awaitable Return Type Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Illustrates how the return type of an awaitable determines the type of the value obtained from a `co_await` expression. This example shows an awaitable returning an integer. ```cpp int i = co_await awaitable_with_int_result(); ``` -------------------------------- ### C++ Detached Coroutine Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Shows how to use a C++ 'detached' coroutine for background operations. The example defines a 'delayed_print' coroutine that prints a message after a delay and is launched from 'co_main'. Detached coroutines cannot be co_returned. ```cpp cobalt::detached delayed_print(std::chrono::milliseconds ms) { asio::steady_timer tim{co_await cobalt::this_coro::executor, ms}; co_await tim.async_wait(cobalt::use_op); printf("Hello world\n"); } cobalt::main co_main(int argc, char *argv[]) { delayed_print(); co_return 0; } ``` -------------------------------- ### C++ Main Coroutine Entry Point Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index The main entry point for the asynchronous server application. It sets up an asynchronous scope using `cobalt::with` to manage resources like the wait group and then runs the server. Returns 0 on successful completion. Requires Boost.Cobalt. ```cpp cobalt::main co_main(int argc, char ** argv) { co_await cobalt::with(cobalt::wait_group(), &run_server); co_return 0u; } ``` -------------------------------- ### Task Execution with cobalt::task and asio::io_context Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Illustrates creating and running a task using `cobalt::task` and integrating with an `asio::io_context` for event loop management. This covers both synchronous (`cobalt::run`) and asynchronous (`cobalt::spawn`) execution. ```cpp cobalt::task my_thread() { // co_await things here co_return; } int main(int argc, char ** argv[]) { cobalt::run(my_task()); // sync asio::io_context ctx; cobalt::spawn(ctx, my_task(), asio::detached); ctx.run(); return 0; } ``` -------------------------------- ### Cobalt Echo Server: Main Coroutine Entry Point (C++) Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index The entry point for the echo server application. It initializes the asynchronous environment and runs the `run_server` coroutine within a `cobalt::with` scope, ensuring proper resource management and graceful shutdown. ```cpp namespace cobalt = boost::cobalt; namespace this_coro = boost::cobalt::this_coro; cobalt::main co_main(int argc, char ** argv) { co_await cobalt::with(cobalt::wait_group(), &run_server); co_return 0u; } ``` -------------------------------- ### C++ Detached Coroutine with Executor Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Shows how to specify an executor for a detached coroutine in C++. The example uses `asio::executor_arg_t` to explicitly provide an `asio::io_context::executor_type` to the `my_gen` function, overriding the default thread-local executor. ```cpp cobalt::detached my_gen(asio::executor_arg_t, asio::io_context::executor_type exec_to_use); ``` -------------------------------- ### Coroutine Entry with cobalt::main Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates how to define a coroutine as the main entry point of the application using `cobalt::main`. This allows coroutines to be used directly within the `main` function. ```cpp cobalt::main co_main(int argc, char* argv[]) { // co_await things here co_return 0; } ``` -------------------------------- ### Coroutine Final Suspend Implementation Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Illustrates a C++ coroutine's `final_suspend` implementation, focusing on how a continuation is handled and when the coroutine frame is destroyed. This example is relevant for understanding coroutine management and potential issues, particularly on compilers like MSVC. ```c++ // in promise auto final_suspend() noexcept { struct final_awaitable { std::coroutine_handle continuation{std::noop_coroutine()}; __**(1)** bool await_ready() const noexcept; std::coroutine_handle await_suspend(std::coroutine_handle h) noexcept { auto cc = continuation; h.destroy(); __**(2)** return cc; } void await_resume() noexcept {} }; return final_awaitable{my_continuation}; }; __**1** | The continuation __**2** | Self-destroying the coroutine before continuation ``` -------------------------------- ### C++ Main Function for Blockchain Connector Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index The core function `run_blockchain_info` orchestrates the price ticker. It connects to blockchain.info, sets up a JSON reader, and uses `cobalt::race` to concurrently handle incoming price updates from the WebSocket and new subscription requests from a channel. ```cpp cobalt::promise run_blockchain_info(cobalt::channel & subc) try { asio::ssl::context ctx{asio::ssl::context_base::tls_client}; websocket_type ws{co_await connect("blockchain.info", ctx)}; co_await connect_to_blockchain_info(ws); __**(1)** subscription_map subs; std::list unconfirmed; auto rd = json_reader(ws); __**(2)** while (ws.is_open()) __**(3)** { switch (auto msg = co_await cobalt::race(rd, subc.read()); msg.index()) __**(4)** { case 0: __**(5)** if (auto ms = get<0>(msg); ms.at("event") == "rejected") // invalid sub, cancel however subbed co_await handle_rejections(unconfirmed, subs, ms); else co_await handle_update(unconfirmed, subs, ms, ws); break; case 1: // __**(6)** co_await handle_new_subscription( unconfirmed, subs, std::move(get<1>(msg)), ws); break; } } for (auto & [k ,c] : subs) { if (auto ptr = c.lock()) ptr->close(); } } catch(std::exception & e) { ``` -------------------------------- ### Get Endpoint Data Function (C++) Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Provides the `get` function to retrieve endpoint data. It uses `get_endpoint_tag` internally and returns a pointer to the data. If the data is not of the expected type, it throws a `bad_endpoint_access` exception. The input is a constant reference to an `endpoint` object. ```cpp // Uses `get_endpoint_tag to return a `pointer` to the result. // Throws `bad_endpoint_access` if it's the wrong type auto get(const endpoint & ep); ``` -------------------------------- ### Main Coroutine with Concurrent Session Management - C++ Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Entry point coroutine that initializes a TCP acceptor on port 8080, creates a subscription channel for managing ticker data requests, and uses Cobalt's join and wait_group to handle up to 10 concurrent WebSocket sessions. Demonstrates parallel task execution and cancellation support with asio::cancellation_type. ```cpp cobalt::main co_main(int argc, char * argv[]) { acceptor_type acc{co_await cobalt::this_coro::executor, asio::ip::tcp::endpoint (asio::ip::tcp::v4(), 8080)}; std::cout << "Listening on localhost:8080" << std::endl; constexpr int limit = 10; cobalt::channel sub_manager; co_await join( run_blockchain_info(sub_manager), cobalt::with( cobalt::wait_group( asio::cancellation_type::all, asio::cancellation_type::all), [&](cobalt::wait_group & sessions) -> cobalt::promise { while (!co_await cobalt::this_coro::cancelled) { if (sessions.size() >= limit) co_await sessions.wait_one(); auto conn = co_await acc.async_accept(); sessions.push_back( run_session( beast::websocket::stream{std::move(conn)}, sub_manager)); } } ); co_return 0; } ``` -------------------------------- ### Cobalt Generator Example: Pushing Values Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Illustrates how to use `cobalt::generator` to push values into the coroutine, where the second template parameter is non-void. The pushed value is received at the `co_yield` point and can be used within the coroutine. This example shows passing a value via `operator()` during `co_await`. ```cpp cobalt::generator example() { printf("In coro 1\n"); int i = co_yield 2; printf("In coro %d\n", i); co_return 4; } cobalt::main co_main(int argc, char * argv[]) { printf("In main 0\n"); auto f = example(); // call and let it run until the first co_yield printf("In main %d\n", co_await f(3)); __**(1)** co_return 0; } ``` -------------------------------- ### Stackless C++20 coroutine example - C++ Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates stackless C++20 coroutine behavior where coroutines only allocate their own frame and use the caller's stack on resumption. The example shows how nested_resume calls within the coroutine create a different call stack pattern compared to traditional function calls. ```cpp fictional_eager_coro_type example() { co_yield 0; co_yield 1; } void nested_resume(fictional_eager_coro_type& f) { f.resume(); } int main() { auto f = example(); nested_resume(f); f.reenter(); return 0; } ``` -------------------------------- ### Coroutine Continuation with Final Suspend Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Illustrates how a coroutine continuation can be handled in the `final_suspend` method of a promise. This example shows the structure of a `final_awaitable` which manages the coroutine's continuation and destruction. ```c++ // in promise auto final_suspend() noexcept { struct final_awaitable { std::coroutine_handle continuation{std::noop_coroutine()}; __**(1)** bool await_ready() const noexcept; std::coroutine_handle await_suspend(std::coroutine_handle h) noexcept { auto cc = continuation; h.destroy(); __**(2)** return cc; } void await_resume() noexcept {} }; return final_awaitable{my_continuation}; }; ``` -------------------------------- ### Querying Execution Context for Any IO Executor (C++) Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Illustrates how to define the query method for execution::context_t, which is required when wrapping an executor in an asio::any_io_executor. This ensures proper management of service lifetimes. ```cpp struct example_executor { asio::execution_context &query(asio::execution::context_t) const; }; ``` -------------------------------- ### Cobalt Main Server Entry Point with Connection Pooling Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Initializes a TCP acceptor on port 8080 and manages concurrent WebSocket sessions using Cobalt coroutines with a configurable connection limit. Joins two parallel tasks: subscription manager and session acceptor with cancellation support. Uses wait_group to enforce a maximum of 10 concurrent sessions and gracefully handles server shutdown. ```cpp cobalt::main co_main(int argc, char * argv[]) { acceptor_type acc{co_await cobalt::this_coro::executor, asio::ip::tcp::endpoint (asio::ip::tcp::v4(), 8080)}; std::cout << "Listening on localhost:8080" << std::endl; constexpr int limit = 10; cobalt::channel sub_manager; co_await join( run_blockchain_info(sub_manager), cobalt::with( cobalt::wait_group( asio::cancellation_type::all, asio::cancellation_type::all), [&](cobalt::wait_group & sessions) -> cobalt::promise { while (!co_await cobalt::this_coro::cancelled) { if (sessions.size() >= limit) co_await sessions.wait_one(); auto conn = co_await acc.async_accept(); sessions.push_back( run_session( beast::websocket::stream{std::move(conn)}, sub_manager)); } } ) ); co_return 0; } ``` -------------------------------- ### Experimental Coroutine Context and Delay Function in C++ Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates the use of `cobalt::experimental::context` to bridge `boost.fiber` stackful coroutines with C20 coroutines. The `delay` function shows how to use `asio::steady_timer` within a coroutine context and `h.await` for asynchronous operations. The `co_main` function illustrates setting up and awaiting a coroutine. ```cpp // void delay(experimental::context> h, std::chrono::milliseconds ms) { asio::steady_timer tim{co_await cobalt::this_coro::executor, ms}; h.await(tim.async_wait(cobalt::use_op)); // instead of co_await. } cobalt::main co_main(int argc, char *argv[]) { cobalt::promise dl = cobalt::experimental::make_context(&delay, 50); co_await dl; co_return 0; } ``` -------------------------------- ### Manage Thread-Local Executor in Cobalt Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Provides functions to get and set the ASIO executor for the current thread. get_executor() throws if not set; set_executor() configures the executor used by coroutines. ```cpp namespace boost::cobalt::this_thread { typename asio::io_context::executor_type & get_executor(); void set_executor(asio::io_context::executor_type exec) noexcept; } ``` -------------------------------- ### Run WebSocket Session with Subscription - C++ Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Coroutine that handles individual WebSocket client sessions, parsing HTTP requests for cryptocurrency pairs (e.g., /btc/usd), accepting WebSocket connections, and forwarding subscription data updates to clients. Includes error handling with try-catch and manages channel lifecycle alongside socket operations. ```cpp cobalt::promise run_session(beast::websocket::stream st, cobalt::channel & subc) try { http::request req; beast::flat_buffer buf; co_await http::async_read(st.next_layer(), buf, req); auto r = urls::parse_uri_reference(req.target()); if (r.has_error() || (r->segments().size() != 2u)) { http::response res{http::status::bad_request, 11}; res.body() = r.has_error() ? r.error().message() : "url needs two segments, e.g. /btc/usd"; co_await http::async_write(st.next_layer(), res); st.next_layer().close(); co_return ; } co_await st.async_accept(req); auto sym = std::string(r->segments().front()) + "-" + std::string(r->segments().back()); boost::algorithm::to_upper(sym); auto p = read_and_close(st, std::move(buf)); auto ptr = std::make_shared>(1u); co_await subc.write(subscription{sym, ptr}); while (ptr->is_open() && st.is_open()) { auto bb = json::serialize(co_await ptr->read()); co_await st.async_write(asio::buffer(bb)); } co_await st.async_close(beast::websocket::close_code::going_away, asio::as_tuple(cobalt::use_op)); st.next_layer().close(); co_await p; } catch(std::exception & e) { std::cerr << "Session ended with exception: " << e.what() << std::endl; } ``` -------------------------------- ### Get Thread-Local Polymorphic Allocator in Cobalt Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Retrieves a polymorphic allocator wrapping the thread's default memory resource. Enables dynamic memory allocation with the configured resource. ```cpp namespace boost::cobalt::this_thread { pmr::polymorphic_allocator get_allocator(); } ``` -------------------------------- ### Executor Property Querying and Modification (C++) Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Demonstrates how an executor can define its properties through query, require, and prefer methods. It shows how to interact with properties like execution relationship and blocking behavior. ```cpp struct example_executor { // get a property by querying it. asio::execution::relationship_t &query(asio::execution::relationship_t) const { return asio::execution::relationship.fork; } // require an executor with a new property never_blocking_executor require(const execution::blocking_t::never_t); // prefer an executor with a new property. the executor may or may not support it. never_blocking_executor prefer(const execution::blocking_t::never_t); // not supported example_executor prefer(const execution::blocking_t::always_t); }; ``` -------------------------------- ### Manage Thread-Local Default Memory Resource in Cobalt Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Provides functions to get and set the default polymorphic memory resource for the current thread. Returns the current resource and previous resource respectively. ```cpp namespace boost::cobalt::this_thread { pmr::memory_resource* get_default_resource() noexcept; pmr::memory_resource* set_default_resource(pmr::memory_resource* r) noexcept; } ``` -------------------------------- ### Minimal Executor Implementation in C++ Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Complete minimal executor interface implementation showing required methods: constructor, context_t query, blocking_t query returning never, execute template function, and equality operators. Serves as a template for custom executor implementations. ```cpp struct minimal_executor { minimal_executor() noexcept; asio::execution_context &query(asio::execution::context_t) const; static constexpr asio::execution::blocking_t query(asio::execution::blocking_t) noexcept { return asio::execution::blocking.never; } template void execute(F && f) const; bool operator==(minimal_executor const &other) const noexcept; bool operator!=(minimal_executor const &other) const noexcept; }; ``` -------------------------------- ### Check Cancellation Status in Cobalt Coroutine Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates two equivalent ways to check the current cancellation status. Both retrieve the cancellation state and call the cancelled() method to get the cancellation type. ```cpp asio::cancellation_type ct = (co_await cobalt::this_coro::cancellation_state).cancelled(); asio::cancellation_type ct = co_await cobalt::this_coro::cancelled; ``` -------------------------------- ### Coroutine Throw If Cancelled Setting (`this_coro`) Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Allows controlling the 'throw if cancelled' behavior within a coroutine. This is achieved through awaitable operations to get or set this state, typically enabled by inheriting from `cobalt::promise_throw_if_cancelled_base`. ```cpp // Functions to get and set throw_if_cancelled setting _unspecified_ throw_if_cancelled(); _unspecified_ throw_if_cancelled(bool value); // Example usage to await the throw_if_cancelled operation co_await cobalt::this_coro::throw_if_cancelled; ``` -------------------------------- ### System Timer Wrapper using asio Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index A system_timer class that wraps an asio::system_timer, offering timer management capabilities. It allows for timer creation with executors, setting expiry times (absolute or relative), cancellation, and querying expiration status. ```cpp struct system_timer { /// The clock type. typedef std::chrono::system_clock clock_type; /// The duration type of the clock. typedef typename clock_type::duration duration; /// The time point type of the clock. typedef typename clock_type::time_point time_point; system_timer(const cobalt::executor & executor = this_thread::get_executor()); system_timer(const time_point& expiry_time, const cobalt::executor & executor = this_thread::get_executor()); system_timer(const duration& expiry_time, const cobalt::executor & executor = this_thread::get_executor()); // cancel the timer. This is safe to call from another thread void cancel(); // The current expiration time. time_point expiry() const; // Rest the expiry time, either with an absolute time or a duration. void reset(const time_point& expiry_time); void reset(const duration& expiry_time); // Check if the timer is already expired. bool expired() const; // Get the wait operation. [[nodiscard]] wait_op wait(); }; ``` -------------------------------- ### Base Socket Operations and Configuration (C++) Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Defines the base 'socket' class for network communication, providing methods for opening, closing, connecting, and managing socket options. It includes compatibility with Asio executors and various low-level socket settings. ```cpp struct socket { [[nodiscard]] system::result open(protocol_type prot = protocol_type {}); [[nodiscard]] system::result close(); [[nodiscard]] system::result cancel(); [[nodiscard]] bool is_open() const; // asio acceptor compatibility template struct rebind_executor { using other = socket; }; using shutdown_type = asio::socket_base::shutdown_type; using wait_type = asio::socket_base::wait_type; using message_flags = asio::socket_base::message_flags; constexpr static int message_peek = asio::socket_base::message_peek; constexpr static int message_out_of_band = asio::socket_base::message_out_of_band; constexpr static int message_do_not_route = asio::socket_base::message_do_not_route; constexpr static int message_end_of_record = asio::socket_base::message_end_of_record; using native_handle_type = asio::basic_socket::native_handle_type; native_handle_type native_handle(); // Drop the connection [[nodiscard]] system::result shutdown(shutdown_type = shutdown_type::shutdown_both); // endpoint of a connected endpiotn [[nodiscard]] system::result local_endpoint() const; [[nodiscard]] system::result remote_endpoint() const; system::result assign(protocol_type protocol, native_handle_type native_handle); system::result release(); /// socket options [[nodiscard]] system::result bytes_readable(); [[nodiscard]] system::result set_debug(bool debug); [[nodiscard]] system::result get_debug() const; [[nodiscard]] system::result set_do_not_route(bool do_not_route); [[nodiscard]] system::result get_do_not_route() const; [[nodiscard]] system::result set_enable_connection_aborted(bool enable_connection_aborted); [[nodiscard]] system::result get_enable_connection_aborted() const; [[nodiscard]] system::result set_keep_alive(bool keep_alive); [[nodiscard]] system::result get_keep_alive() const; [[nodiscard]] system::result set_linger(bool linger, int timeout); [[nodiscard]] system::result> get_linger() const; [[nodiscard]] system::result set_receive_buffer_size(std::size_t receive_buffer_size); [[nodiscard]] system::result get_receive_buffer_size() const; [[nodiscard]] system::result set_send_buffer_size(std::size_t send_buffer_size); [[nodiscard]] system::result get_send_buffer_size() const; [[nodiscard]] system::result set_receive_low_watermark(std::size_t receive_low_watermark); [[nodiscard]] system::result get_receive_low_watermark() const; [[nodiscard]] system::result set_send_low_watermark(std::size_t send_low_watermark); [[nodiscard]] system::result get_send_low_watermark() const; [[nodiscard]] system::result set_reuse_address(bool reuse_address); [[nodiscard]] system::result get_reuse_address() const; [[nodiscard]] system::result set_no_delay(bool reuse_address); [[nodiscard]] system::result get_no_delay() const; wait_op wait(wait_type wt = wait_type::wait_read); // Connect to a specific endpoint connect_op connect(endpoint ep); // connect to one of the given endpoints. Returns the one connected to. ranged_connect_op connect(endpoint_sequence ep); protected: // Adopt the under-specified endpoint. E.g. to tcp from an endpoint specified as ip_address virtual void adopt_endpoint_(endpoint & ) {} }; // Connect to sockets using the given protocol system::result connect_pair(protocol_type protocol, socket & socket1, socket & socket2); ``` -------------------------------- ### Immediate Completion with Cobalt Task Source: https://www.boost.org/doc/libs/latest/libs/cobalt/index Benchmarks immediate operation completion using a channel with a size of 1. The `cobalt::task` function demonstrates sending and receiving operations that complete immediately due to the channel's buffer size. ```c++ cobalt::task atest() { asio::experimental::channel chan{co_await cobalt::this_coro::executor, 1u}; for (std::size_t i = 0u; i < n; i++) { co_await chan.async_send(system::error_code{}, cobalt::use_op); co_await chan.async_receive(cobalt::use_op); } } ``` -------------------------------- ### C++ Declarations for Price Ticker Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Sets up type aliases and namespaces required for the price ticker application, including executor, socket, acceptor, and websocket stream types. ```cpp using executor_type = cobalt::use_op_t::executor_with_default; using socket_type = typename asio::ip::tcp::socket::rebind_executor::other; using acceptor_type = typename asio::ip::tcp::acceptor::rebind_executor::other; using websocket_type = beast::websocket::stream>; namespace http = beast::http; ``` -------------------------------- ### C++ Task Coroutine with Allocator Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Illustrates how to define a C++ task coroutine that accepts a custom memory resource via `std::allocator_arg` and `pmr::polymorphic_allocator`. This allows for explicit control over memory allocation for the coroutine's state. ```cpp cobalt::task my_gen(std::allocator_arg_t, pmr::polymorphic_allocator alloc); ``` -------------------------------- ### C++ Detached Coroutine with Cancellation Example Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Demonstrates how to manage cancellation for a detached coroutine in C++. A `asio::cancellation_signal` is used to control the coroutine's lifetime. The `my_task` function accepts a `cancellation_slot` and uses `this_coro::reset_cancellation_source` to integrate with the provided signal. ```cpp cobalt::detached my_task(asio::cancellation_slot sl) { co_await this_coro::reset_cancellation_source(sl); // do somework } cobalt::main co_main(int argc, char *argv[]) { asio::cancellation_signal sig; my_task(sig.slot()); __**(1)** co_await delay(std::chrono::milliseconds(50)); sig.emit(asio::cancellation_type::all); co_return 0; } ``` -------------------------------- ### C++ Function to Upgrade to WebSocket Source: https://www.boost.org/doc/libs/latest/libs/cobalt/doc/html/index Upgrades an existing SSL stream to a WebSocket connection targeting blockchain.info. It sets necessary HTTP headers, including User-Agent and Origin, and performs the WebSocket handshake. Requires Beast and Cobalt libraries. ```cpp cobalt::promise connect_to_blockchain_info(websocket_type & ws) { ws.set_option(beast::websocket::stream_base::decorator( [](beast::websocket::request_type& req) { req.set(http::field::user_agent, std::string(BOOST_BEAST_VERSION_STRING) + " cobalt-ticker"); req.set(http::field::origin, "https://exchange.blockchain.com"); })); co_await ws.async_handshake("ws.blockchain.info", "/mercury-gateway/v1/ws"); } ```