### Launch Fibers and Threads with Work-Sharing - Boost Fiber Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/work_sharing Main function that installs the shared_work scheduling algorithm, launches 26 detached worker fibers with character parameters, creates 3 worker threads, and synchronizes all fibers using a barrier and condition variable. ```C++ int main( int argc, char *argv[]) { std::cout << "main thread started " << std::this_thread::get_id() << std::endl; boost::fibers::use_scheduling_algorithm< boost::fibers::algo::shared_work >(); for ( char c : std::string("abcdefghijklmnopqrstuvwxyz")) { boost::fibers::fiber([c](){ whatevah( c); }).detach(); ++fiber_count; } boost::fibers::detail::thread_barrier b( 4); std::thread threads[] = { std::thread( thread, & b), std::thread( thread, & b), std::thread( thread, & b) }; b->wait(); { lock_type lk( mtx_count); cnd_count.wait( lk, [](){ return 0 == fiber_count; } ); } } ``` -------------------------------- ### Example Usage of wait_first_success Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/wait_stuff Demonstrates how to use the wait_first_success function. The first example shows a successful execution where a function returns a string. The second example illustrates the case where all functions throw exceptions, and an exception_list is caught. ```cpp // example usage Example wfss( runner, "wait_first_success()", [](){ //[wait_first_success_ex std::string result = wait_first_success( [](){ return sleeper("wfss_first", 50, true); }, [](){ return sleeper("wfss_second", 100); }, [](){ return sleeper("wfss_third", 150); }); std::cout << "wait_first_success(success) => " << result << std::endl; assert(result == "wfss_second"); //] std::string thrown; std::size_t count = 0; try { result = wait_first_success( [](){ return sleeper("wfsf_first", 50, true); }, [](){ return sleeper("wfsf_second", 100, true); }, [](){ return sleeper("wfsf_third", 150, true); }); } catch ( exception_list const& e) { thrown = e.what(); count = e.size(); } catch ( std::exception const& e) { thrown = e.what(); } std::cout << "wait_first_success(fail) threw '" << thrown << "': " << count << " errors" << std::endl; assert(thrown == "wait_first_success() produced only errors"); assert(count == 3); }); ``` -------------------------------- ### Example Usage of wait_first_value_het Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/wait_stuff This example demonstrates the usage of `wait_first_value_het` with functions returning different types (string, double, int). It shows how to capture the `boost::variant` result and extract the specific type using `boost::get`. ```cpp // example usage Example wfvh( runner, "wait_first_value_het()", [](){ //[wait_first_value_het_ex boost::variant< std::string, double, int > result = wait_first_value_het( [](){ return sleeper("wfvh_third", 150); }, [](){ return sleeper(3.14, 100); }, [](){ return sleeper(17, 50); }); std::cout << "wait_first_value_het() => " << result << std::endl; assert(boost::get< int >( result) == 17); //] }); ``` -------------------------------- ### Boost.Fiber Buffered Channel: Range-based for Loop Example (C++) Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/synchronization/channels/buffered_channel Illustrates using a range-based for loop to iterate over elements in a Boost.Fiber buffered_channel. This syntax simplifies consuming messages from the channel, making the code more readable. The example shows pushing several integers into the channel and then consuming them using the for loop. ```cpp #include #include typedef boost::fibers::buffered_channel< int > channel_t; void foo( channel_t & chan) { chan.push( 1); chan.push( 1); chan.push( 2); chan.push( 3); chan.push( 5); chan.push( 8); chan.push( 12); chan.close(); } void bar( channel_t & chan) { for ( unsigned int value : chan) { std::cout << value << " "; } std::cout << std::endl; } int main() { channel_t chan{ 2 }; // Assuming foo and bar are called in separate fibers or sequentially // For demonstration, let's call them sequentially: foo(chan); bar(chan); return 0; } ``` -------------------------------- ### Boost Fibers Barrier Synchronization Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/priority This example showcases the use of `boost::fibers::barrier` to synchronize multiple fibers. A barrier is created with a count of 3, and three fibers are launched that will all wait at the barrier. The barrier ensures that all waiting fibers are woken up simultaneously once the required number of fibers have reached the barrier, demonstrating a common pattern for parallel task coordination. ```cpp { Verbose v("barrier wakes up all", "stop\n"); // using a barrier wakes up all waiting fibers at the same time boost::fibers::barrier barrier( 3); boost::fibers::fiber low( launch( [&barrier](){ barrier_fn( barrier); }, "low", 1) ); boost::fibers::fiber med( launch( [&barrier](){ barrier_fn( barrier); }, "medium", 2) ); boost::fibers::fiber hi( launch( [&barrier](){ barrier_fn( barrier); }, "high", 3) ); std::cout << "main: low.join()" << std::endl; low.join(); std::cout << "main: medium.join()" << std::endl; med.join(); std::cout << "main: high.join()" << std::endl; hi.join(); } ``` -------------------------------- ### Example usage of wait_all_values_source (C++) Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/when_any/when_all_functionality/when_all__return_values This example shows how to use `wait_all_values_source` to get a channel and then process the results as they become available. It demonstrates popping values from the channel in a loop until it's closed. ```cpp std::shared_ptr< boost::fibers::buffered_channel< std::string > > chan = wait_all_values_source( [](){ return sleeper("wavs_third", 150); }, [](){ return sleeper("wavs_second", 100); }, [](){ return sleeper("wavs_first", 50); }); std::string value; while ( boost::fibers::channel_op_status::success == chan->pop(value) ) { std::cout << "wait_all_values_source() => '" << value << "'" << std::endl; } ``` -------------------------------- ### wait_all_simple Usage Example - Lambda Tasks Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/wait_stuff Example demonstrating how to use wait_all_simple with three lambda functions that call a sleeper function with different durations. The function blocks until all three tasks complete, useful for coordinating parallel work in fiber-based applications. ```C++ wait_all_simple( [](){ sleeper("was_long", 150); }, [](){ sleeper("was_medium", 100); }, [](){ sleeper("was_short", 50); }); ``` -------------------------------- ### Round-Robin Scheduling for Same-Priority Fibers Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/priority This code segment demonstrates the round-robin scheduling behavior for Boost Fibers when multiple fibers share the same priority. Three fibers (`a`, `b`, `c`) are created with a priority of 0. The example shows that these fibers are executed in the order they were created, confirming the round-robin approach for equal priorities within the scheduler. ```cpp { Verbose v("same priority round-robin", "stop\n"); // fibers of same priority are scheduled in round-robin order boost::fibers::fiber a( launch( yield_fn, "a", 0) ); boost::fibers::fiber b( launch( yield_fn, "b", 0) ); boost::fibers::fiber c( launch( yield_fn, "c", 0) ); std::cout << "main: a.join()" << std::endl; a.join(); std::cout << "main: b.join()" << std::endl; b.join(); std::cout << "main: c.join()" << std::endl; c.join(); } ``` -------------------------------- ### Set and retrieve value using promise and future in C++ with Boost.Fiber Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/synchronization/futures This example illustrates the lower-level usage of `boost::fibers::promise<>` to explicitly set a value in an associated `boost::fibers::future<>`. It shows how to create a promise, get its future, set the value, and then retrieve it, verifying the state of the future. ```cpp boost::fibers::promise pi; boost::fibers::future fi; fi=pi.get_future(); pi.set_value(42); assert(fi.is_ready()); assert(fi.has_value()); assert(!fi.has_exception()); assert(fi.get()==42); ``` -------------------------------- ### wait_first_outcome Usage Example C++ Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/wait_stuff Demonstrates practical usage of wait_first_outcome() with lambda functions of different execution times. Shows both successful execution (returning the fastest result) and exception handling when the first completing function throws an exception. ```C++ std::string result = wait_first_outcome( [](){ return sleeper("wfos_first", 50); }, [](){ return sleeper("wfos_second", 100); }, [](){ return sleeper("wfos_third", 150); }); std::cout << "wait_first_outcome(success) => " << result << std::endl; assert(result == "wfos_first"); std::string thrown; try { result = wait_first_outcome( [](){ return sleeper("wfof_first", 50, true); }, [](){ return sleeper("wfof_second", 100); }, [](){ return sleeper("wfof_third", 150); }); } catch ( std::exception const& e) { thrown = e.what(); } std::cout << "wait_first_outcome(fail) threw '" << thrown << "'" << std::endl; assert(thrown == "wfof_first"); ``` -------------------------------- ### Fiber Launching Utility Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/priority A template function to launch a new fiber with a given function, name, and priority. It encapsulates the process of creating a `boost::fibers::fiber` object and setting its properties, including name and priority. ```cpp //[launch template< typename Fn > boost::fibers::fiber launch( Fn && func, std::string const& name, int priority) { boost::fibers::fiber fiber( func); priority_props & props( fiber.properties< priority_props >() ); props.name = name; props.set_priority( priority); return fiber; } //] ``` -------------------------------- ### wait_all_members with Data Struct Example Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/wait_stuff Demonstrates using `wait_all_members` to execute three asynchronous `sleeper` functions and collect their results into a `Data` struct. It shows both a successful execution and a scenario where exceptions are thrown, catching and reporting them. ```cpp Data data = wait_all_members< Data >( [](){ return sleeper("wams_left", 100); }, [](){ return sleeper(3.14, 150); }, [](){ return sleeper(17, 50); }); std::cout << "wait_all_members(success) => " << data << std::endl; std::string thrown; try { data = wait_all_members< Data >( [](){ return sleeper("wamf_left", 100, true); }, [](){ return sleeper(3.14, 150); }, [](){ return sleeper(17, 50, true); }); std::cout << "wait_all_members(fail) => " << data << std::endl; } catch ( std::exception const& e) { thrown = e.what(); } std::cout << "wait_all_members(fail) threw '" << thrown << '"' << std::endl; ``` -------------------------------- ### wait_all_values Example Usage Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/wait_stuff Demonstrates calling wait_all_values with multiple lambda functions that return strings after delays, collecting all results into a vector and iterating through them. ```C++ std::vector< std::string > values = wait_all_values( [](){ return sleeper("wav_late", 150); }, [](){ return sleeper("wav_middle", 100); }, [](){ return sleeper("wav_early", 50); }); std::cout << "wait_all_values() =>"; for ( std::string const& v : values) { std::cout << " '" << v << "'"; } std::cout << std::endl; ``` -------------------------------- ### Setup Shared Work Scheduling in Worker Thread Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/migration Installs the shared_work scheduling algorithm in a worker thread to join the fiber work sharing pool. Synchronizes thread startup with a barrier and suspends the main fiber until all worker fibers are complete. Uses a condition variable to detect when fiber_count reaches zero. ```C++ void thread( boost::fibers::detail::thread_barrier * b) { std::ostringstream buffer; buffer << "thread started " << std::this_thread::get_id() << std::endl; std::cout << buffer.str() << std::flush; boost::fibers::use_scheduling_algorithm< boost::fibers::algo::shared_work >(); b->wait(); lock_type lk( mtx_count); cnd_count.wait( lk, [](){ return 0 == fiber_count; } ); BOOST_ASSERT( 0 == fiber_count); } ``` -------------------------------- ### Custom Fiber Scheduler: describe_ready_queue Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/priority A utility function to print the current state of the ready queue for debugging purposes. It iterates through the fibers in the queue and displays their names and priorities. ```cpp void describe_ready_queue() { if ( rqueue_.empty() ) { std::cout << "[empty]"; } else { const char * delim = ""; for ( boost::fibers::context & ctx : rqueue_) { priority_props & props( properties( & ctx) ); std::cout << delim << props.name << '(' << props.get_priority() << ')'; delim = ", "; } } std::cout << std::endl; } ``` -------------------------------- ### Example usage of wait_first_simple with sleeper functions Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/when_any/when_any/when_any__simple_completion This example demonstrates how to use the `wait_first_simple` function to concurrently execute three `sleeper` functions with different durations. The program will resume execution after the shortest `sleeper` function completes, even if the others are still running. This highlights the 'first one wins' nature of the simple completion pattern. ```C++ wait_first_simple( [](){ sleeper("wfs_long", 150); }, [](){ sleeper("wfs_medium", 100); }, [](){ sleeper("wfs_short", 50); }); ``` -------------------------------- ### wait_all_members with std::vector Example Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/wait_stuff Illustrates using `wait_all_members` to execute multiple asynchronous `sleeper` functions returning strings and collecting them into a `std::vector`. This example highlights the flexibility of `wait_all_members` in handling different return types and order of results. ```cpp auto strings = wait_all_members< std::vector< std::string > >( [](){ return sleeper("wamv_left", 150); }, [](){ return sleeper("wamv_middle", 100); }, [](){ return sleeper("wamv_right", 50); }); std::cout << "wait_all_members() ="; for ( std::string const& str : strings) { std::cout << " '" << str << "'"; } std::cout << std::endl; ``` -------------------------------- ### Fiber Synchronization: barrier_fn Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/priority A sample fiber function that waits on a `boost::fibers::barrier`. Once the barrier is passed, the fiber yields execution. It retrieves its name from the fiber's properties. ```cpp void barrier_fn( boost::fibers::barrier & barrier) { std::string name( boost::this_fiber::properties< priority_props >().name); Verbose v( std::string("fiber ") + name); std::cout << "fiber " << name << " waiting on barrier" << std::endl; barrier.wait(); std::cout << "fiber " << name << " yielding" << std::endl; boost::this_fiber::yield(); } ``` -------------------------------- ### Example usage of wait_all_values (C++) Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/when_any/when_all_functionality/when_all__return_values This example demonstrates how to call the `wait_all_values` function with multiple lambda functions that simulate work using `sleeper`. The results are collected into a `std::vector`. ```cpp std::vector< std::string > values = wait_all_values( [](){ return sleeper("wav_late", 150); }, [](){ return sleeper("wav_middle", 100); }, [](){ return sleeper("wav_early", 50); }); ``` -------------------------------- ### High-Priority Fiber Scheduling in Boost Fibers Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/priority This example illustrates the behavior of a priority scheduler where a high-priority fiber is guaranteed to be scheduled before lower-priority ones. It creates three fibers with different priorities (low, medium, high) and demonstrates that the `hi` fiber completes its execution first, followed by `med`, and then `low`, verifying the priority-based scheduling. ```cpp std::cout << "main() running tests" << std::endl; { Verbose v("high-priority first", "stop\n"); // verify that high-priority fiber always gets scheduled first boost::fibers::fiber low( launch( yield_fn, "low", 1) ); boost::fibers::fiber med( launch( yield_fn, "medium", 2) ); boost::fibers::fiber hi( launch( yield_fn, "high", 3) ); std::cout << "main: high.join()" << std::endl; hi.join(); std::cout << "main: medium.join()" << std::endl; med.join(); std::cout << "main: low.join()" << std::endl; low.join(); } ``` -------------------------------- ### Install Fiber Scheduler and Launch Worker Fibers in main() Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/migration Installs the shared_work scheduling algorithm in the main thread and creates detached worker fibers that process characters. Uses thread barriers to synchronize threads and condition variables to wait for all fibers to complete before joining threads. The main fiber suspends until all worker fibers finish their work. ```C++ boost::fibers::use_scheduling_algorithm< boost::fibers::algo::shared_work >(); for ( char c : std::string("abcdefghijklmnopqrstuvwxyz")) { boost::fibers::fiber([c](){ whatevah( c); }).detach(); ++fiber_count; } boost::fibers::detail::thread_barrier b( 4); std::thread threads[] = { std::thread( thread, & b), std::thread( thread, & b), std::thread( thread, & b) }; b.wait(); { lock_type lk( mtx_count); cnd_count.wait( lk, [](){ return 0 == fiber_count; } ); } BOOST_ASSERT( 0 == fiber_count); for ( std::thread & t : threads) { t.join(); } ``` -------------------------------- ### Fiber Execution: yield_fn Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/priority A sample fiber function that demonstrates yielding execution. The fiber yields control back to the scheduler three times. It retrieves its name from the fiber's properties. ```cpp void yield_fn() { std::string name( boost::this_fiber::properties< priority_props >().name); Verbose v( std::string("fiber ") + name); for ( int i = 0; i < 3; ++i) { std::cout << "fiber " << name << " yielding" << std::endl; boost::this_fiber::yield(); } } ``` -------------------------------- ### Initiate io_service Run Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/integration/deeper_dive_into___boost_asio__ This snippet shows the application initiating the io_service to start processing events and fibers. The `run()` method will not return immediately if a `work` instance is present, allowing asynchronous operations to proceed. ```cpp io_ctx->run(); ``` -------------------------------- ### Create Exception Helper Function (C++) Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/adapt_method_calls A helper function `make_exception` is provided to construct `std::runtime_error` objects with descriptive messages, including the API method and error code. This promotes consistent error reporting within the asynchronous API. ```cpp std::runtime_error make_exception( std::string const& desc, AsyncAPI::errorcode ec) { std::ostringstream buffer; buffer << "Error in AsyncAPI::" << desc << "(): " << ec; return std::runtime_error( buffer.str() ); } ``` -------------------------------- ### Example Nonblocking API Definition Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/nonblocking Defines a C++ class `NonblockingAPI` with a `read` method that exemplifies nonblocking I/O. This method may return `EWOULDBLOCK` if the operation cannot complete immediately, requiring the caller to retry. ```cpp class NonblockingAPI { public: NonblockingAPI(); // nonblocking operation: may return EWOULDBLOCK int read( std::string & data, std::size_t desired); ... }; ``` -------------------------------- ### Custom Fiber Scheduler: has_ready_fibers Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/priority Implements the `has_ready_fibers` method for a custom fiber scheduler. This method checks if there are any fibers ready to run in the scheduler's ready queue. It is essential for informing the fiber manager about the scheduler's state. ```cpp /*<< You must override [member_link algorithm_with_properties..has_ready_fibers] to inform the fiber manager of the state of your ready queue. >>*/ virtual bool has_ready_fibers() const noexcept { return ! rqueue_.empty(); } ``` -------------------------------- ### Example Task Function: sleeper_impl Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/when_any A templated implementation for an asynchronous task function. It simulates work by sleeping for a specified duration, optionally throws an exception, and returns an item. This function is used to demonstrate various waiting mechanisms. ```cpp template< typename T > T sleeper_impl( T item, int ms, bool thrw = false) { std::ostringstream descb, funcb; descb << item; std::string desc( descb.str() ); funcb << " sleeper(" << item << ")"; Verbose v( funcb.str() ); boost::this_fiber::sleep_for( std::chrono::milliseconds( ms) ); if ( thrw) { throw std::runtime_error( desc); } return item; } ``` -------------------------------- ### Launch Fibers for Server and Client Operations Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/integration/deeper_dive_into___boost_asio__ This C++ snippet shows how to launch server and client fibers after setting up the Boost.Asio scheduler. It demonstrates creating a server fiber that accepts connections and multiple client fibers that connect and perform operations, using a `boost::fibers::barrier` for synchronization. ```cpp // server tcp::acceptor a( * io_ctx, tcp::endpoint( tcp::v4(), 9999) ); boost::fibers::fiber( server, io_ctx, std::ref( a) ).detach(); // client const unsigned iterations = 2; const unsigned clients = 3; boost::fibers::barrier b( clients); for ( unsigned i = 0; i < clients; ++i) { boost::fibers::fiber( client, io_ctx, std::ref( a), std::ref( b), iterations).detach(); } ``` -------------------------------- ### Define Custom Fiber Properties for Priority Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/priority The `priority_props` class extends `boost::fibers::fiber_properties` to store and manage a fiber's priority. It includes methods to get and set the priority, ensuring that changes to priority trigger a notification to the scheduler. Non-scheduler-affecting properties, like the fiber's name, can be public data members. ```cpp #include #include class Verbose { public: Verbose( std::string const& d, std::string const& s="stop") : desc( d), stop( s) { std::cout << desc << " start" << std::endl; } ~Verbose() { std::cout << desc << ' ' << stop << std::endl; } Verbose( Verbose const&) = delete; Verbose & operator=( Verbose const&) = delete; private: std::string desc; std::string stop; }; //[priority_props class priority_props : public boost::fibers::fiber_properties { public: priority_props( boost::fibers::context * ctx): fiber_properties( ctx), priority_( 0) { } int get_priority() const { return priority_; } void set_priority( int p) { if ( p != priority_) { priority_ = p; notify(); } } std::string name; private: int priority_; }; //] ``` -------------------------------- ### Boost.Fiber Synopsis and Includes Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/fiber_mgmt This snippet provides the necessary include directive and the synopsis for the Boost.Fiber library, outlining the core classes and functions available for fiber management. It includes definitions for `fiber`, `fiber::id`, `this_fiber` namespace functionalities, and scheduling algorithms. ```cpp #include namespace boost { namespace fibers { class fiber; bool operator<( fiber const& l, fiber const& r) noexcept; void swap( fiber & l, fiber & r) noexcept; template< typename SchedAlgo, typename ... Args > void use_scheduling_algorithm( Args && ... args); bool has_ready_fibers(); namespace algo { struct algorithm; template< typename PROPS > struct algorithm_with_properties; class round_robin; class shared_round_robin; } }} namespace this_fiber { fibers::id get_id() noexcept; void yield(); template< typename Clock, typename Duration > void sleep_until( std::chrono::time_point< Clock, Duration > const& abs_time) template< typename Rep, typename Period > void sleep_for( std::chrono::duration< Rep, Period > const& rel_time); template< typename PROPS > PROPS & properties(); } ``` -------------------------------- ### Initialize ASIO IO Context with Boost.Fiber Round-Robin Scheduler Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/asio/autoecho Sets up an ASIO io_context and configures Boost.Fiber to use the round-robin scheduling algorithm. This initialization is required before launching fiber-based tasks that perform asynchronous I/O operations. The io_context is shared across all fibers via std::shared_ptr. ```C++ std::shared_ptr< boost::asio::io_context > io_ctx = std::make_shared< boost::asio::io_context >(); boost::fibers::use_scheduling_algorithm< boost::fibers::asio::round_robin >( io_ctx); ``` -------------------------------- ### Boost.Asio round_robin Scheduler Constructor Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/integration/deeper_dive_into___boost_asio__ This C++ code illustrates the constructor for the `asio::round_robin` scheduler. It initializes the `io_context` member and a `boost::asio::steady_timer`, and crucially adds a custom `service` to the `io_context` using `boost::asio::add_service`. ```cpp round_robin( std::shared_ptr< boost::asio::io_context > const& io_ctx) : io_ctx_( io_ctx), suspend_timer_( * io_ctx_) { // Ensure that the service is added only once per io_context boost::asio::add_service( * io_ctx_, new service( * io_ctx_) ); boost::asio::post( * io_ctx_, [this]() mutable { // Lambda to be executed asynchronously }); } ``` -------------------------------- ### Boost.Fiber: future<> get() Member Functions Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/synchronization/futures/future The `get()` member function family is used to retrieve the result of an asynchronous operation. It blocks until the promise associated with the future has set a value or an exception. It then returns the value or throws the exception. After calling `get()`, the future becomes invalid. Specializations exist for generic types, references, and void. ```cpp R get(); // member only of generic future template R & get(); // member only of future< R & > template specialization void get(); // member only of future< void > template specialization ``` -------------------------------- ### Implement Fake Asynchronous API with Threading (C++) Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/adapt_method_calls Provides a concrete, albeit fake, implementation of an asynchronous API (`AsyncAPI`). The `init_read` method simulates an I/O operation by launching a detached thread that sleeps before calling the provided `Response` callback. This allows testing of asynchronous patterns without actual I/O. ```cpp class AsyncAPI: public AsyncAPIBase { public: // constructor acquires some resource that can be read AsyncAPI( std::string const& data); //[method_init_read // derive Response subclass, instantiate, pass Response::ptr void init_read( Response::ptr); //] // ... other operations ... void inject_error( errorcode ec); private: std::string data_; errorcode injected_; }; /***************************************************************************** * fake AsyncAPI implementation... pay no attention to the little man behind * the curtain... *****************************************************************************/ AsyncAPI::AsyncAPI( std::string const& data) : data_( data), injected_( 0) { } void AsyncAPI::inject_error( errorcode ec) { injected_ = ec; } void AsyncAPI::init_read( Response::ptr response) { // make a local copy of injected_ errorcode injected( injected_); // reset it synchronously with caller injected_ = 0; // local copy of data_ so we can capture in lambda std::string data( data_); // Simulate an asynchronous I/O operation by launching a detached thread // that sleeps a bit before calling either completion method. std::thread( [injected, response, data](){ std::this_thread::sleep_for( std::chrono::milliseconds(100) ); if ( ! injected) { // no error, call success() response->success( data); } else { // injected error, call error() response->error( injected); } }).detach(); } ``` -------------------------------- ### Initialize Boost.Asio Scheduler for Fibers Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/integration/deeper_dive_into___boost_asio__ This C++ snippet demonstrates how to initialize the Boost.Asio round_robin scheduling algorithm for Boost.Fibers. It requires a shared pointer to a `boost::asio::io_context` and uses `boost::fibers::use_scheduling_algorithm` to set the custom scheduler. ```cpp std::shared_ptr< boost::asio::io_context > io_ctx = std::make_shared< boost::asio::io_context >(); bool ret = boost::fibers::use_scheduling_algorithm< boost::fibers::asio::round_robin >( io_ctx); if ( !ret) { // Handle error: scheduling algorithm could not be set } ``` -------------------------------- ### Launch Multiple Fibers with Detach and Barrier Coordination Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/asio/autoecho Demonstrates creating and detaching multiple client fibers that coordinate through a shared barrier. Creates a server fiber and specified number of client fibers, each running independently. Uses std::ref to pass barrier and acceptor references to fiber functions. ```C++ // server tcp::acceptor a( * io_ctx, tcp::endpoint( tcp::v4(), 9999) ); boost::fibers::fiber( server, io_ctx, std::ref( a) ).detach(); // client const unsigned iterations = 2; const unsigned clients = 3; boost::fibers::barrier b( clients); for ( unsigned i = 0; i < clients; ++i) { boost::fibers::fiber( client, io_ctx, std::ref( a), std::ref( b), iterations).detach(); } ``` -------------------------------- ### Define Data Struct for wait_all_members Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/wait_stuff Defines a `Data` struct to hold results from asynchronous operations. It includes string, double, and int members. This struct is used as a result type in `wait_all_members` examples. It also overloads the `operator<<` for easy printing of `Data` objects. ```cpp struct Data { std::string str; double inexact; int exact; friend std::ostream& operator<<(std::ostream& out, Data const& data) { return out << "Data{str='" << data.str << "', inexact=" << data.inexact << ", exact=" << data.exact << "}"; } }; ``` -------------------------------- ### Implement Synchronous Read Using Async API and Futures (C++) Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/adapt_method_calls The `read` function demonstrates how to use the asynchronous `AsyncAPI` in a synchronous manner. It creates a `PromiseResponse`, retrieves its `future`, initiates the asynchronous read operation via `api.init_read()`, and then blocks on `future.get()` until the operation completes, returning the result. ```cpp //[method_read std::string read( AsyncAPI & api) { // Because init_read() requires a shared_ptr, we must allocate our // ResponsePromise on the heap, even though we know its lifespan. auto promisep( std::make_shared< PromiseResponse >() ); boost::fibers::future< std::string > future( promisep->get_future() ); // Both 'promisep' and 'future' will survive until our lambda has been // called. api.init_read( promisep); return future.get(); } //] ``` -------------------------------- ### wait_first_value Usage Example - Boost.Fiber Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/when_any/when_any/when_any__return_value Example demonstrating how to call wait_first_value with multiple lambda functions that perform time-delayed operations. The function returns the result from whichever lambda completes first (shortest delay), with assertion verifying the expected fastest function completed. ```cpp std::string result = wait_first_value( [](){ return sleeper("wfv_third", 150); }, [](){ return sleeper("wfv_second", 100); }, [](){ return sleeper("wfv_first", 50); }); std::cout << "wait_first_value() => " << result << std::endl; assert(result == "wfv_first"); ``` -------------------------------- ### Initialize Priority Scheduler for Boost Fibers Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/priority This snippet demonstrates how to configure the Boost Fibers library to use a custom `priority_scheduler` instead of the default round-robin scheduler. This is achieved by calling `boost::fibers::use_scheduling_algorithm` before creating any fibers, ensuring that all subsequent fibers will be managed by the priority-based scheduling policy. ```cpp //[main int main( int argc, char *argv[]) { // make sure we use our priority_scheduler rather than default round_robin boost::fibers::use_scheduling_algorithm< priority_scheduler >(); /*= ...* /*=}*/ //] Verbose v("main()") ; // for clarity std::cout << "main() setting name" << std::endl; //[main_name boost::this_fiber::properties< priority_props >().name = "main"; //] ``` -------------------------------- ### Implement wait_all_simple_impl for Recursive Fiber Launch Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/when_any/when_all_functionality/when_all__simple_completion This C++ code implements the `wait_all_simple_impl` function, which recursively launches fibers. Each launched fiber executes a provided function and then signals completion by calling `barrier->wait()`. This function is a helper for `wait_all_simple`, handling the detailed logic of fiber creation and synchronization. ```cpp template< typename Fn, typename ... Fns > void wait_all_simple_impl( std::shared_ptr< boost::fibers::barrier > barrier, Fn && function, Fns && ... functions) { boost::fibers::fiber( std::bind( []( std::shared_ptr< boost::fibers::barrier > & barrier, typename std::decay< Fn >::type & function) mutable { function(); barrier->wait(); }, barrier, std::forward< Fn >( function) )).detach(); wait_all_simple_impl( barrier, std::forward< Fns >( functions) ... ); } ``` -------------------------------- ### async_result_base Constructor and get() - Fiber Suspension and Error Handling Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/callbacks/then_there_s____boost_asio__ Manages the lifecycle of asynchronous operations by creating yield_completion state, injecting it into the handler, and providing a get() method that suspends the fiber until completion. Handles error code binding and throws system_error if the async operation reports an error. ```cpp // Factor out commonality between async_result> and // async_result> class async_result_base { public: explicit async_result_base( yield_handler_base & h) : ycomp_{ new yield_completion{} } { // Inject ptr to our yield_completion instance into this // yield_handler<>. h.ycomp_ = this->ycomp_; // if yield_t didn't bind an error_code, make yield_handler_base's // error_code* point to an error_code local to this object so // yield_handler_base::operator() can unconditionally store through // its error_code* if ( ! h.yt_.ec_) { h.yt_.ec_ = & ec_; } } void get() { // Unless yield_handler_base::operator() has already been called, // suspend the calling fiber until that call. ycomp_->wait(); // The only way our own ec_ member could have a non-default value is // if our yield_handler did not have a bound error_code AND the // completion callback passed a non-default error_code. if ( ec_) { throw_exception( boost::system::system_error{ ec_ } ); } } private: // If yield_t does not bind an error_code instance, store into here. boost::system::error_code ec_{}; yield_completion::ptr_t ycomp_; }; ``` -------------------------------- ### Boost.Fiber Buffered Channel: Send and Receive Messages (C++) Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/synchronization/channels/buffered_channel Demonstrates sending and receiving integer messages using Boost.Fiber's buffered_channel. It shows how to initialize a channel, push values into it, close the channel, and pop values until the channel is empty or closed. This example highlights basic asynchronous message passing between two fibers. ```cpp #include #include #include #include typedef boost::fibers::buffered_channel< int > channel_t; void send( channel_t & chan) { for ( int i = 0; i < 5; ++i) { chan.push( i); } chan.close(); } void recv( channel_t & chan) { int i; while ( boost::fibers::channel_op_status::success == chan.pop(i) ) { std::cout << "received " << i << std::endl; } } int main() { channel_t chan{ 2 }; boost::fibers::fiber f1( std::bind( send, std::ref( chan) ) ); boost::fibers::fiber f2( std::bind( recv, std::ref( chan) ) ); f1.join(); f2.join(); return 0; } ``` -------------------------------- ### Boost Fiber ASIO Round Robin Scheduler Header Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/asio/round_robin Header guard and includes for the round-robin fiber scheduler. Includes dependencies for chrono timing, memory management, synchronization (mutex/queue), Boost.ASIO for I/O operations, and Boost.Fiber components for context and scheduler management. This file provides the foundation for cooperative multitasking with asynchronous I/O integration. ```cpp // Copyright Oliver Kowalke 2013. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_FIBERS_ASIO_ROUND_ROBIN_H #define BOOST_FIBERS_ASIO_ROUND_ROBIN_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "yield.hpp" #ifdef BOOST_HAS_ABI_HEADERS ``` -------------------------------- ### wait_all_simple - Synchronize Multiple Fiber Tasks with Barrier Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/wait_stuff Template function that instantiates a barrier, launches multiple fiber tasks as forwarded functions, and waits for all to complete. Uses a shared_ptr barrier initialized with count+1 to ensure the calling fiber waits until all passed functions have executed. Requires Boost.Fiber library and variadic template support. ```C++ template< typename ... Fns > void wait_all_simple( Fns && ... functions) { std::size_t count( sizeof ... ( functions) ); auto barrier( std::make_shared< boost::fibers::barrier >( count + 1) ); wait_all_simple_impl( barrier, std::forward< Fns >( functions) ... ); barrier->wait(); } ``` -------------------------------- ### Specialize async_result for yield_handler Value Storage and Retrieval Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/callbacks/then_there_s____boost_asio__ The async_result specialization for yield_handler reserves a member variable of type T to store the completion value and injects a pointer to it into the yield_handler. The get() method calls the base class get() to suspend the fiber, then returns the stored value when resumed. This enables the calling fiber to receive the asynchronous result. ```cpp template< typename ReturnType, typename T > class async_result< boost::fibers::asio::yield_t, ReturnType(boost::system::error_code, T) > : public boost::fibers::asio::detail::async_result_base { public: using return_type = T; using completion_handler_type = fibers::asio::detail::yield_handler; explicit async_result( boost::fibers::asio::detail::yield_handler< T > & h) : boost::fibers::asio::detail::async_result_base{ h } { h.value_ = & value_; } return_type get() { boost::fibers::asio::detail::async_result_base::get(); return std::move( value_); } private: return_type value_{}; }; ``` -------------------------------- ### Create and use packaged_task for asynchronous value retrieval in C++ Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/synchronization/futures This snippet demonstrates how to use `boost::fibers::packaged_task<>` to wrap a function, launch it on a fiber, and retrieve its return value using a `boost::fibers::future<>`. It covers task creation, future retrieval, fiber detachment, waiting for completion, and asserting the result. ```cpp int calculate_the_answer_to_life_the_universe_and_everything() { return 42; } boost::fibers::packaged_task pt(calculate_the_answer_to_life_the_universe_and_everything); boost::fibers::future fi=pt.get_future(); boost::fibers::fiber(std::move(pt)).detach(); // launch task on a fiber fi.wait(); // wait for it to finish assert(fi.is_ready()); assert(fi.has_value()); assert(!fi.has_exception()); assert(fi.get()==42); ``` -------------------------------- ### wait_first_outcome Usage Example: Concurrent Lambda Execution Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/when_any/when_any/when_any__produce_first_outcome__whether_result_or_exception Example demonstrating how to call wait_first_outcome() with multiple lambda functions as task candidates. The first lambda to complete returns its result (either a value or exception) to the caller. This pattern is useful for implementing race conditions where you need the outcome of whichever task finishes first. ```C++ std::string result = wait_first_outcome( [](){ return sleeper("wfos_first", 50); }, [](){ return sleeper("wfos_second", 100); } ``` -------------------------------- ### Get End Iterator for Unbuffered Channel Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/synchronization/channels/unbuffered_channel Returns an end range-iterator for the unbuffered channel. This function is templated on the channel type T and returns an input-iterator. ```cpp template< typename T > unbuffered_channel< R >::iterator end( unbuffered_channel< T > &); ``` -------------------------------- ### Write Adapter Using Boost Fiber Promise Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/adapt_callbacks Demonstrates the beginning of a write_ec adapter function that converts the callback-based AsyncAPI::init_write into a synchronous fiber operation using boost::fibers::promise to wait for the asynchronous callback result. ```cpp AsyncAPI::errorcode write_ec( AsyncAPI & api, std::string const& data) { boost::fibers::promise< AsyncAPI::errorcode > promise; ``` -------------------------------- ### Get Begin Iterator for Unbuffered Channel Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/synchronization/channels/unbuffered_channel Returns a range-iterator for the beginning of the unbuffered channel. This function is templated on the channel type T and returns an input-iterator. ```cpp template< typename T > unbuffered_channel< T >::iterator begin( unbuffered_channel< T > &); ``` -------------------------------- ### Get begin iterator for Boost.Fiber channel Source: https://www.boost.org/doc/libs/latest/libs/fiber/doc/html/fiber/synchronization/channels/buffered_channel Returns an input-iterator to the beginning of the channel's elements. This allows for range-based iteration over the channel's contents. ```cpp template< typename T > buffered_channel< T >::iterator begin( buffered_channel< T > &); ``` -------------------------------- ### wait_all_members Function Template Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/wait_stuff The `wait_all_members` function template from Boost Fibers. It takes a result type and a variadic list of functions. It launches each function in a separate fiber using `boost::fibers::async` and then collects their results, returning them as the specified `Result` type. ```cpp template< typename Result, typename ... Fns > Result wait_all_members( Fns && ... functions) { return wait_all_members_get< Result >( boost::fibers::async( std::forward< Fns >( functions) ) ... ); } ``` -------------------------------- ### Fiber Synchronization: notify Source: https://www.boost.org/doc/libs/latest/libs/fiber/examples/priority Wakes up all fibers that are currently waiting on the condition variable (`cnd_`). It sets a flag (`flag_`) to true before notifying, indicating that the condition has been met. ```cpp void notify() noexcept { std::unique_lock< std::mutex > lk( mtx_); flag_ = true; lk.unlock(); cnd_.notify_all(); } ```