### Boost.Coroutine2 Coroutine Chaining Example (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/motivation This C++ code illustrates chaining multiple coroutines to process a string data stream. It defines functions for reading lines, tokenizing, filtering words, tracing tokens, and laying out output. The example demonstrates constructing coroutine chains using `std::bind` and `std::ref` with both pull-type and push-type interfaces. ```cpp typedef boost::coroutines2::coroutine coro_t; // deliver each line of input stream to sink as a separate string void readlines(coro_t::push_type& sink,std::istream& in){ std::string line; while(std::getline(in,line)) sink(line); } void tokenize(coro_t::push_type& sink, coro_t::pull_type& source){ // This tokenizer doesn't happen to be stateful: you could reasonably // implement it with a single call to push each new token downstream. But // I've worked with stateful tokenizers, in which the meaning of input // characters depends in part on their position within the input line. for(std::string line:source){ std::string::size_type pos=0; while(pos::push_type coro( [&](boost::coroutines2::coroutine::pull_type& yield){ coro(); }); coro(); ``` -------------------------------- ### C++ Boost Coroutine2 push_type Example Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric Demonstrates creating a boost::coroutines2::coroutine<>::push_type to transfer strings from a std::vector to a coroutine function. The coroutine function formats the strings into lines of a specified width. The example highlights inversion of control and uses std::copy for data transfer. ```cpp #include #include #include #include #include #include #include typedef boost::coroutines2::coroutine coro_t; struct FinalEOL{ ~FinalEOL(){ std::cout << std::endl; } }; const int num = 5, width = 15; coro_t::push_type writer( [&](coro_t::pull_type& in){ // finish the last line when we leave by whatever means FinalEOL eol; // pull values from upstream, lay them out 'num' to a line for (;;){ for(int i=0; i words{ "peas", "porridge", "hot", "peas", "porridge", "cold", "peas", "porridge", "in", "the", "pot", "nine", "days", "old" }; std::copy(begin(words),end(words),begin(writer)); // Output: // peas porridge hot peas porridge // cold peas porridge in the // pot nine days old ``` -------------------------------- ### C++ Asio Coroutine-Based Asynchronous Read Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/motivation Illustrates a C++ Asio approach using coroutines for asynchronous operations, allowing for sequential-style code. This example shows initiating an asynchronous read operation and suspending execution until data is available. ```cpp void session(boost::asio::io_service& io_service){ // construct TCP-socket from io_service boost::asio::ip::tcp::socket socket(io_service); try{ for(;;){ // local data-buffer char data[max_length]; boost::system::error_code ec; // read asynchronous data from socket // execution context will be suspended until // some bytes are read from socket ``` -------------------------------- ### Accessing Coroutine Parameters (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric Shows how to access parameters passed to or returned from coroutine functions using `get()`. This allows checking the validity of the coroutine state after context switches. ```cpp typedef boost::coroutines2::coroutine> coro_t; coro_t::push_type sink( [&](coro_t::pull_type& source){ // access tuple {7,11}; x==7 y==1 int x,y; boost::tie(x,y)=source.get(); }); sink(boost::make_tuple(7,11)); ``` -------------------------------- ### Coroutine Result Retrieval (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric/pull_coro Documents the `get()` member function for `coroutine<>::pull_type`, which retrieves the value yielded by the coroutine. It specifies the return types for different `R` template parameters and notes potential usage restrictions for move-only types. ```cpp R get() noexcept; // Preconditions: `*this` is not a _not-a-coroutine_. // Returns: Returns data transferred from coroutine-function via _coroutine <>::push_type::operator()_. // Throws: `invalid_result` // Note: If `R` is a move-only type, you may only call `get()` once before the next _coroutine <>::pull_type::operator()_ call. ``` -------------------------------- ### C++ Asio Callback-Based Asynchronous Read/Write Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/motivation Demonstrates a classic C++ Asio implementation of an echo server using callback functions for asynchronous read and write operations. State is managed through member variables, and control flow is managed by the event loop. ```cpp class session { public: session(boost::asio::io_service& io_service) : socket_(io_service) // construct a TCP-socket from io_service {} tcp::socket& socket(){ return socket_; } void start(){ // initiate asynchronous read; handle_read() is callback-function socket_.async_read_some(boost::asio::buffer(data_,max_length), boost::bind(&session::handle_read,this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } private: void handle_read(const boost::system::error_code& error, size_t bytes_transferred){ if (!error) // initiate asynchronous write; handle_write() is callback-function boost::asio::async_write(socket_, boost::asio::buffer(data_,bytes_transferred), boost::bind(&session::handle_write,this, boost::asio::placeholders::error)); else delete this; } void handle_write(const boost::system::error_code& error){ if (!error) // initiate asynchronous read; handle_read() is callback-function socket_.async_read_some(boost::asio::buffer(data_,max_length), boost::bind(&session::handle_read,this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); else delete this; } boost::asio::ip::tcp::socket socket_; enum { max_length=1024 }; char data_[max_length]; }; ``` -------------------------------- ### Asynchronous Socket Read/Write with Coroutines Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/motivation Demonstrates asynchronous socket read and write operations using Boost Coroutine2. It simulates sequential code execution by yielding control during I/O operations and handles errors within a single try-catch block. Dependencies include Boost.ASIO and Boost.System. ```cpp std::size_t length=socket.async_read_some( boost::asio::buffer(data), boost::asio::yield[ec]); if (ec==boost::asio::error::eof) break; //connection closed cleanly by peer else if(ec) throw boost::system::system_error(ec); //some other error // write some bytes asynchronously boost::asio::async_write( socket, boost::asio::buffer(data,length), boost::asio::yield[ec]); if (ec==boost::asio::error::eof) break; //connection closed cleanly by peer else if(ec) throw boost::system::system_error(ec); //some other error } catch(std::exception const& e){ std::cerr<<"Exception: "< ``` -------------------------------- ### Coroutine Pull Type Constructors and Assignment Operators (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric/pull_coro Details the constructors and move assignment operator for the `coroutine<>::pull_type` class. These functions are responsible for initializing and managing coroutine instances, including handling stack allocation and transferring coroutine state. ```cpp template< typename Fn > pull_type( Fn && fn); // Effects: Creates a coroutine which will execute `fn`, and enters it. // Throws: Exceptions thrown inside _coroutine-function_. template< typename StackAllocator, typename Fn > pull_type( StackAllocator stack_alloc, Fn && fn); // Effects: Creates a coroutine which will execute `fn`. For allocating/deallocating the stack `stack_alloc` is used. // Throws: Exceptions thrown inside _coroutine-function_. ~pull_type(); // Effects: Destroys the context and deallocates the stack. pull_type( pull_type && other) noexcept; // Effects: Moves the internal data of `other` to `*this`. `other` becomes _not-a-coroutine_. // Throws: Nothing. pull_type & operator=( pull_type && other) noexcept; // Effects: Destroys the internal data of `*this` and moves the internal data of `other` to `*this`. `other` becomes _not-a-coroutine_. // Throws: Nothing. ``` -------------------------------- ### Stack Allocator Concept Requirements Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/stack This table defines the essential operations and their expected behavior for a type to satisfy the _stack-allocator concept_. It includes creating an allocator, allocating a stack context, and deallocating a previously allocated context. The `allocate()` function may include overflow protection. ```text expression | return type | notes a(size) | | creates a stack allocator a.allocate() | stack_context | creates a stack a.deallocate( sctx) | void | deallocates the stack created by a.allocate() ``` -------------------------------- ### Boost Coroutine2 push_type Constructors and Destructor (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric/push_coro Details the constructors and destructor for `coroutine<>::push_type`. The constructors allow for creating a coroutine that executes a given function `fn`, optionally using a custom `StackAllocator`. The destructor ensures proper cleanup of the coroutine context and its allocated stack. ```cpp template< typename Fn > push_type( Fn && fn); template< typename StackAllocator, typename Fn > push_type( StackAllocator stack_alloc, Fn && fn); ~push_type(); ``` -------------------------------- ### Boost Coroutine2 push_type Class Definition (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric/push_coro Defines the `coroutine<>::push_type` class template, which serves as the handle for coroutines that allow for pushing control flow. It includes constructors for creating coroutines with or without custom stack allocators, copy/move operations, a destructor, boolean conversion operators to check coroutine status, an invocation operator to resume coroutine execution, and declarations for non-member `begin` and `end` functions for iteration. ```cpp #include template< typename Arg > class coroutine<>::push_type { public: template< typename Fn > push_type( Fn && fn); template< typename StackAllocator, typename Fn > push_type( StackAllocator stack_alloc, Fn && fn); push_type( push_type const& other)=delete; push_type & operator=( push_type const& other)=delete; ~push_type(); push_type( push_type && other) noexcept; push_type & operator=( push_type && other) noexcept; explicit operator bool() const noexcept; bool operator!() const noexcept; push_type & operator()( Arg arg); }; template< typename Arg > range_iterator< push_type< Arg > >::type begin( push_type< Arg > &); template< typename Arg > range_iterator< push_type< Arg > >::type end( push_type< Arg > &); ``` -------------------------------- ### Define Boost.Coroutine2 stack_context Structure (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/stack/stack_context Defines the `stack_context` structure used in Boost.Coroutine2. It holds a pointer to the stack's beginning (`sp`) and its total size (`size`). This structure may include additional fields for segmented stack implementations. ```cpp struct stack_context { void * sp; std::size_t size; // might contain additional control structures // for segmented stacks } ``` -------------------------------- ### Create Left Tree Structure for 'Same Fringe' Problem Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/motivation A C++ function to construct a specific left-leaning tree structure used in the 'same fringe' problem demonstration. It creates a tree with a root and a left subtree, facilitating testing of sequence comparison. ```cpp node::ptr_t create_left_tree_from(const std::string& root){ /* -------- root / \ b e / \ a c -------- */ return node::create( node::create( node::create("a"), "b", node::create("c")), root, node::create("e")); } ``` -------------------------------- ### Compare Tree Fringes Using Coroutines and std::equal Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/motivation This C++ code snippet demonstrates the 'same fringe' problem solution. It creates two trees, sets up pull coroutines to traverse them, and then uses std::equal to compare the sequences of values generated by the coroutines. The output indicates whether the trees have the same fringe. ```cpp // evaluation { node::ptr_t left_d(create_left_tree_from("d")); coro_t::pull_type left_d_reader([&](coro_t::push_type & out){ traverse(left_d,out); }); node::ptr_t right_b(create_right_tree_from("b")); coro_t::pull_type right_b_reader([&](coro_t::push_type & out){ traverse(right_b,out); }); std::cout << "left tree from d == right tree from b? " << std::boolalpha << std::equal(begin(left_d_reader), end(left_d_reader), begin(right_b_reader)) << std::endl; } { node::ptr_t left_d(create_left_tree_from("d")); coro_t::pull_type left_d_reader([&](coro_t::push_type & out){ traverse(left_d,out); }); node::ptr_t right_x(create_right_tree_from("x")); coro_t::pull_type right_x_reader([&](coro_t::push_type & out){ traverse(right_x,out); }); std::cout << "left tree from d == right tree from x? " << std::boolalpha << std::equal(begin(left_d_reader), end(left_d_reader), begin(right_x_reader)) << std::endl; } std::cout << "Done" << std::endl; ``` -------------------------------- ### Create Right Tree Structure for 'Same Fringe' Problem Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/motivation A C++ function to construct a specific right-leaning tree structure used in the 'same fringe' problem demonstration. It creates a tree with a root and a right subtree, enabling the comparison of different tree structures with potentially the same fringe. ```cpp node::ptr_t create_right_tree_from(const std::string& root){ /* -------- root / \ a d / \ c e -------- */ return node::create( node::create("a"), root, node::create( node::create("c"), "d", node::create("e"))); } ``` -------------------------------- ### allocate() Method for pooled_fixedsize_stack (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/stack/pooled_fixedsize Allocates memory for a stack context using the `pooled_fixedsize_stack`. It ensures sufficient memory is available based on the stack size and system architecture. The allocated memory pointer and size are stored in the provided `stack_context`. ```cpp stack_context allocate() ``` -------------------------------- ### Class pooled_fixedsize_stack Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/stack/pooled_fixedsize The pooled_fixedsize_stack class manages stack memory using an internal boost::pool. It provides methods for construction, allocation, and deallocation of stacks. ```APIDOC ## Class pooled_fixedsize_stack ### Description The `boost::coroutine2::pooled_fixedsize_stack` class models the _stack-allocator concept_. Unlike `protected_fixedsize_stack`, it does not use a guard page. Memory is managed internally by `boost::pool<>`. ### Constructor `pooled_fixedsize_stack(std::size_t stack_size, std::size_t next_size, std::size_t max_size)` **Parameters:** * `stack_size` (std::size_t) - The size of each stack to be allocated. * `next_size` (std::size_t) - The number of stacks to request from the system initially. * `max_size` (std::size_t) - The maximum amount of memory that can be allocated for stacks (0 for no limit). **Preconditions:** `! traits_type::is_unbounded() && ( traits_type::maximum:size() >= stack_size)` and `0 < nest_size`. **Effects:** Allocates memory for stacks. The stored address is the highest/lowest address depending on the stack growth direction. `next_size` determines the initial system memory request, and `max_size` sets an upper limit on allocated memory. ### Methods #### `stack_context allocate()` **Description:** Allocates memory for a stack. **Preconditions:** `! traits_type::is_unbounded() && ( traits_type::maximum:size() >= size)`. **Effects:** Allocates at least `size` bytes and stores the stack pointer and its size in `sctx`. The stored address is the highest/lowest address depending on the stack growth direction. #### `void deallocate( stack_context & sctx)` **Description:** Deallocates the previously allocated stack space. **Parameters:** * `sctx` (stack_context &) - A reference to the stack context to deallocate. **Preconditions:** `sctx.sp` is valid, `! traits_type::is_unbounded() && ( traits_type::maximum:size() >= sctx.size)`. **Effects:** Frees the memory associated with the provided stack context. ``` -------------------------------- ### Generate Fibonacci Numbers with pull_type Coroutine C++ Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric Creates an asymmetric coroutine using coroutine<>::pull_type to generate Fibonacci numbers in a separate execution context. The coroutine-function calculates Fibonacci values and transfers them back to the main context via push_type. Demonstrates context switching, data transfer, and iteration using range-based for-loops with input iterators. ```cpp typedef boost::coroutines2::coroutine coro_t; coro_t::pull_type source( [&](coro_t::push_type& sink){ int first=1,second=1; sink(first); sink(second); for(int i=0;i<8;++i){ int third=first+second; first=second; second=third; sink(third); } }); for(auto i:source) std::cout << i << " "; // output: // 1 1 2 3 5 8 13 21 34 55 ``` -------------------------------- ### protected_fixedsize Stack Allocator Class Definition Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/stack/protected_fixedsize Defines the protected_fixedsize struct which models the stack-allocator concept for Boost.Coroutine2. Includes constructor initialization with optional size parameter and core allocation/deallocation methods. The guard page mechanism protects against stack overflow by triggering a segmentation fault on access. ```cpp #include struct protected_fixedsize { protected_fixesize(std::size_t size = traits_type::default_size()); stack_context allocate(); void deallocate( stack_context &); } ``` -------------------------------- ### Stack Unwinding in Boost.Coroutine2 Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric Demonstrates stack unwinding for coroutines to release resources using RAII. The coroutine constructor's attributes control stack unwinding. Unwinding completes the coroutine. Preconditions for unwinding include the coroutine not being 'not-a-coroutine', not complete, not running, and owning a stack. ```cpp #include #include struct X { X() { std::cout << "X()" << std::endl; } ~X() { std::cout << "~X()" << std::endl; } }; int main() { typedef boost::coroutines2::coroutine coro_t; coro_t::push_type sink( [&](coro_t::pull_type& source) { X x; for (int i = 0; ; ++i) { std::cout << "fn(): " << i << std::endl; // transfer execution control back to main() source(); } }); sink(); sink(); sink(); sink(); sink(); std::cout << "sink is complete: " << std::boolalpha << !sink << "\n"; return 0; } ``` -------------------------------- ### Recursive Descent Parser with Coroutines Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/motivation Implements a recursive descent parser using Boost Coroutine2 to invert control flow. The parser yields individual characters as they are processed, allowing the calling code to consume them. This approach simplifies error handling by enabling the caller to wrap the coroutine execution in a try-catch block. Dependencies include Boost.Coroutines2, functional, and iostream. ```cpp class Parser{ char next; std::istream& is; std::function cb; char pull(){ return std::char_traits::to_char_type(is.get()); } void scan(){ do{ next=pull(); } while(isspace(next)); } public: Parser(std::istream& is_,std::function cb_) : next(), is(is_), cb(cb_) {} void run() { scan(); E(); } private: void E(){ T(); while (next=='+'||next=='-'){ cb(next); scan(); T(); } } void T(){ S(); while (next=='*'||next=='/'){ cb(next); scan(); S(); } } void S(){ if (std::isdigit(next)){ cb(next); scan(); } else if(next=='('){ cb(next); scan(); E(); if (next==')'){ cb(next); scan(); }else{ throw parser_error(); } } else{ throw parser_error(); } } }; typedef boost::coroutines2::coroutine< char > coro_t; int main() { std::istringstream is("1+1"); // invert control flow coro_t::pull_type seq( boost::coroutines2::fixedsize_stack(), [&is](coro_t::push_type & yield) { // create parser with callback function Parser p( is, [&yield](char ch){ // resume user-code yield(ch); }); // start recursive parsing p.run(); }); // user-code pulls parsed data from parser // invert control flow for(char c:seq){ printf("Parsed: %c\n",c); } } ``` -------------------------------- ### Define Tree Node Structure for 'Same Fringe' Problem Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/motivation Defines a 'node' structure to represent a tree with string values and shared pointers to child nodes. Includes constructors for leaf and non-leaf nodes, and static factory methods for creating nodes. This structure is fundamental for the tree traversal logic. ```cpp struct node{ typedef std::shared_ptr ptr_t; // Each tree node has an optional left subtree, // an optional right subtree and a value of its own. // The value is considered to be between the left // subtree and the right. ptr_t left,right; std::string value; // construct leaf node(const std::string& v): left(),right(),value(v) {} // construct nonleaf node(ptr_t l,const std::string& v,ptr_t r): left(l),right(r),value(v) {} static ptr_t create(const std::string& v){ return ptr_t(new node(v)); } static ptr_t create(ptr_t l,const std::string& v,ptr_t r){ return ptr_t(new node(l,v,r)); } }; ``` -------------------------------- ### fixedsize_stack Class Definition Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/stack/fixedsize Defines the fixedsize_stack class, a component of Boost.Coroutine2 that manages stack memory. It utilizes std::malloc and std::free for allocation and deallocation, and differs from protected_fixedsize_stack by not appending a guard page. The class provides methods to allocate and deallocate stack contexts. ```cpp #include struct fixedsize_stack { fixedsize_stack(std::size_t size = traits_type::default_size()); stack_context allocate(); void deallocate( stack_context &); } ``` -------------------------------- ### Exception Handling in Coroutines (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric Explains how exceptions are propagated in Boost.Coroutine2. Exceptions thrown in a pull-coroutine are re-thrown by the constructor or `operator()`, while exceptions in a push-coroutine are re-thrown by `operator()`. It also includes a critical note on not absorbing `detail::forced_unwind`. ```cpp try { // code that might throw } catch(const boost::context::detail::forced_unwind&) { throw; } catch(...) { // possibly not re-throw pending exception } ``` -------------------------------- ### Class fixedsize_stack Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/stack/fixedsize The fixedsize_stack class provides functionality to allocate and deallocate stack memory. It manages memory using std::malloc and std::free and does not append a guard page. ```APIDOC ## Class fixedsize_stack ### Description Models the stack-allocator concept. It allocates memory using `std::malloc()` and `std::free()` without appending a guard page. ### Method `fixedsize_stack(std::size_t size = traits_type::default_size())` ### Parameters * **size** (std::size_t) - Optional - The size of the stack to allocate. Defaults to `traits_type::default_size()`. --- ## stack_context allocate() ### Description Allocates memory for a stack. ### Method `stack_context allocate() ` ### Preconditions `traits_type::minimum_size() <= size` and `! traits_type::is_unbounded() && ( traits_type::maximum_size() >= size)`. ### Effects Allocates memory of at least `size` Bytes and stores a pointer to the stack and its actual size in `sctx`. Depending on the architecture (the stack grows downwards/upwards) the stored address is the highest/lowest address of the stack. ### Response #### Success Response (200) - **sctx** (stack_context) - A structure containing the stack pointer and its size. --- ## void deallocate( stack_context & sctx) ### Description Deallocates the previously allocated stack space. ### Method `void deallocate( stack_context & sctx)` ### Parameters * **sctx** (stack_context) - Required - A reference to the stack_context structure representing the stack to be deallocated. ### Preconditions `sctx.sp` is valid, `traits_type::minimum_size() <= sctx.size` and `! traits_type::is_unbounded() && ( traits_type::maximum_size() >= sctx.size)`. ### Effects Deallocates the stack space. ``` -------------------------------- ### Pass Data from Main Context to Push-Coroutine (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric Illustrates sending data from the main context into a coroutine (push_type). The main context uses a push_type object to send values, and the coroutine uses a pull_type argument to receive them. ```cpp typedef boost::coroutines2::coroutine coro_t; coro_t::push_type sink( // constructor does NOT enter coroutine-function [&](coro_t::pull_type& source){ for (int i:source) { std::cout << i << " "; } }); std::vector v{1,1,2,3,5,8,13,21,34,55}; for( int i:v){ sink(i); // push {i} to coroutine-function } ``` -------------------------------- ### Boost Coroutine2 push_type Move Operations (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric/push_coro Describes the move constructor and move assignment operator for `coroutine<>::push_type`. These operations allow efficient transfer of ownership of a coroutine's internal state from one `push_type` object to another, leaving the source object in a non-coroutine state. They are designed to be `noexcept`. ```cpp push_type( push_type && other) noexcept; push_type & operator=( push_type && other) noexcept; ``` -------------------------------- ### Pass Data from Pull-Coroutine to Main Context (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric Demonstrates transferring data from a coroutine (pull_type) back to the main context. The coroutine uses a push_type argument to send values, and the main context uses pull_type to receive and test for validity. ```cpp typedef boost::coroutines2::coroutine coro_t; coro_t::pull_type source( // constructor enters coroutine-function [&](coro_t::push_type& sink){ sink(1); // push {1} back to main-context sink(1); // push {1} back to main-context sink(2); // push {2} back to main-context sink(3); // push {3} back to main-context sink(5); // push {5} back to main-context sink(8); // push {8} back to main-context }); while(source){ // test if pull-coroutine is valid int ret=source.get(); // access data value source(); // context-switch to coroutine-function } ``` -------------------------------- ### Range Output Iterators with Boost.Coroutine2 Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric Demonstrates creating output iterators from `boost::coroutines2::coroutine::push_type` using Boost.Range. This enables sending data into a coroutine using standard algorithms like `std::copy`. The iterator's dereference operation corresponds to the coroutine's call operator. ```cpp #include #include #include #include #include int main() { typedef boost::coroutines2::coroutine coro_t; coro_t::push_type sink( [&](coro_t::pull_type& source) { while (source) { std::cout << source.get() << " "; source(); } }); std::vector v{1, 1, 2, 3, 5, 8, 13, 21, 34, 55}; std::copy(begin(v), end(v), begin(sink)); std::cout << std::endl; return 0; } ``` -------------------------------- ### Traverse Tree and Yield Values with Coroutine Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/motivation A C++ coroutine function that recursively traverses a tree and yields each node's value in order using a Boost.Coroutine2 push coroutine. This function provides the sequence of leaf node values for comparison. ```cpp typedef boost::coroutines2::coroutine coro_t; // recursively walk the tree, delivering values in order void traverse(node::ptr_t n, coro_t::push_type& out){ if(n->left) traverse(n->left,out); out(n->value); if(n->right) traverse(n->right,out); } ``` -------------------------------- ### pooled_fixedsize_stack Class Definition (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/stack/pooled_fixedsize Defines the `pooled_fixedsize_stack` class from Boost.Coroutine2. This class manages stack memory for coroutines using an internal memory pool. It includes a constructor and methods for allocating and deallocating stack contexts. ```cpp #include struct pooled_fixedsize_stack { pooled_fixedsize_stack(std::size_t size = traits_type::default_size()); stack_context allocate(); void deallocate( stack_context &); } ``` -------------------------------- ### Boost.Coroutine2 Segmented Stack Class Definition Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/stack/segmented Defines the `segmented_stack` structure, which manages stack allocation for coroutines. It supports on-demand growth and adheres to the stack-allocator concept. This class is specifically supported by GCC 4.7+ and Clang 3.4+ and requires specific build configurations. ```cpp #include struct segmented_stack { segmented_stack(std::size_t size = traits_type::default_size()); stack_context allocate(); void deallocate( stack_context &); } ``` -------------------------------- ### Coroutine State and Execution Control (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric/pull_coro Explains the methods used to control the execution of a `coroutine<>::pull_type` and check its state. The `operator()` transfers control to the coroutine, while `operator bool()` and `operator!()` indicate whether the coroutine is active or has completed. ```cpp pull_coroutine & operator()(); // Preconditions: `*this` is not a _not-a-coroutine_. // Effects: Execution control is transferred to _coroutine-function_ (no parameter is passed to the coroutine-function). // Throws: Exceptions thrown inside _coroutine-function_. explicit operator bool() const noexcept; // Returns: If `*this` refers to _not-a-coroutine_ or the coroutine-function has returned (completed), the function returns `false`. Otherwise `true`. // Throws: Nothing. bool operator!() const noexcept; // Returns: If `*this` refers to _not-a-coroutine_ or the coroutine-function has returned (completed), the function returns `true`. Otherwise `false`. // Throws: Nothing. ``` -------------------------------- ### Coroutine Range Iterators (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric/pull_coro Provides declarations for the non-member `begin()` and `end()` functions, which return range iterators for `coroutine<>::pull_type`. These functions enable the use of range-based for loops and other range-based algorithms with coroutines. ```cpp template< typename R > range_iterator< pull_type< R > >::type begin( pull_type< R > &); // Returns: Returns a range-iterator (input-iterator). template< typename R > range_iterator< pull_type< R > >::type end( pull_type< R > &); // Returns: Returns an end range-iterator (input-iterator). // Note: When first obtained from `begin( pull_type< R > &)`, or after some number of increment operations, an iterator will compare equal to the iterator returned by `end( pull_type< R > &)` when the corresponding _coroutine <>::pull_type::operator bool_ would return `false`. ``` -------------------------------- ### Coroutine Pull Type Class Definition (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric/pull_coro Defines the `coroutine<>::pull_type` class, a fundamental component for creating pull-based coroutines in Boost.Coroutine2. It outlines the class's public interface for constructing, managing, and interacting with coroutines, including methods for execution, state checking, and result retrieval. ```cpp #include template< typename R > class coroutine<>::pull_type { public: template< typename Fn > pull_type( Fn && fn); template< typename StackAllocator, typename Fn > pull_type( StackAllocator stack_alloc, Fn && fn); pull_type( pull_type const& other)=delete; pull_type & operator=( pull_type const& other)=delete; ~pull_type(); pull_type( pull_type && other) noexcept; pull_type & operator=( pull_type && other) noexcept; pull_coroutine & operator()(); explicit operator bool() const noexcept; bool operator!() const noexcept; R get() noexcept; }; template< typename R > range_iterator< pull_type< R > >::type begin( pull_type< R > &); template< typename R > range_iterator< pull_type< R > >::type end( pull_type< R > &); ``` -------------------------------- ### deallocate() Method - Stack Memory Deallocation Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/stack/protected_fixedsize Deallocates previously allocated stack space referenced by the stack_context parameter. Preconditions verify that the stack pointer is valid and the stack size remains within the minimum and maximum bounds. Must be called with a valid stack_context obtained from a prior allocate() call. ```cpp void deallocate( stack_context & sctx); ``` -------------------------------- ### allocate() Method - Stack Memory Allocation Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/stack/protected_fixedsize Allocates memory of at least the specified size in bytes and stores stack pointer and actual size in the stack_context object. The stored address represents either the highest or lowest stack address depending on architecture (downward or upward stack growth). Preconditions require the requested size to be within minimum and maximum bounds defined by traits_type. ```cpp stack_context allocate(); ``` -------------------------------- ### deallocate() Method for pooled_fixedsize_stack (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/stack/pooled_fixedsize Deallocates stack space previously allocated by `pooled_fixedsize_stack`. It takes a `stack_context` object containing the stack pointer and size to be freed. Preconditions verify the validity of the stack pointer and size. ```cpp void deallocate( stack_context & sctx) ``` -------------------------------- ### Boost Coroutine2 push_type Non-member begin/end Functions (C++) Source: https://www.boost.org/doc/libs/latest/libs/coroutine2/doc/html/coroutine2/coroutine/asymmetric/push_coro Describes the non-member `begin` and `end` functions for `coroutine<>::push_type`. These functions return range iterators, allowing the coroutine to be used within range-based for loops or other range-based algorithms. The `end` iterator typically signifies the completion of the coroutine. ```cpp template< typename Arg > range_iterator< push_type< Arg > >::type begin( push_type< Arg > &); template< typename Arg > range_iterator< push_type< Arg > >::type end( push_type< Arg > &); ```