Boost
C++ Libraries
...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
This is an older version of Boost and was released in 2021. The current version is 1.90.0.
One classic approach to completion notification is to define an abstract
base class with success()
and error()
methods. Code wishing to perform async I/O must derive a subclass, override
each of these methods and pass the async operation a pointer to a subclass
instance. The abstract base class might look like this:
// every async operation receives a subclass instance of this abstract base // class through which to communicate its result struct Response { typedef std::shared_ptr< Response > ptr; // called if the operation succeeds virtual void success( std::string const& data) = 0; // called if the operation fails virtual void error( AsyncAPIBase::errorcode ec) = 0; };
Now the AsyncAPI operation
might look more like this:
// derive Response subclass, instantiate, pass Response::ptr void init_read( Response::ptr);
We can address this by writing a one-size-fits-all PromiseResponse:
class PromiseResponse: public Response { public: // called if the operation succeeds virtual void success( std::string const& data) { promise_.set_value( data); } // called if the operation fails virtual void error( AsyncAPIBase::errorcode ec) { promise_.set_exception( std::make_exception_ptr( make_exception("read", ec) ) ); } boost::fibers::future< std::string > get_future() { return promise_.get_future(); } private: boost::fibers::promise< std::string > promise_; };
Now we can simply obtain the future<> from that PromiseResponse
and wait on its get():
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(); }
The source code above is found in adapt_callbacks.cpp and adapt_method_calls.cpp.