...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
But a more natural API for a function that obtains data is to return only the data on success, throwing an exception on error.
As with write()
above, it’s certainly possible to code a read()
wrapper in terms of read_ec()
. But since a given application is unlikely
to need both, let’s code read()
from scratch, leveraging promise::set_exception()
:
std::string read( AsyncAPI & api) { boost::fibers::promise< std::string > promise; boost::fibers::future< std::string > future( promise.get_future() ); // Both 'promise' and 'future' will survive until our lambda has been // called. #if ! defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES) api.init_read([&promise]( AsyncAPI::errorcode ec, std::string const& data) mutable { if ( ! ec) { promise.set_value( data); } else { promise.set_exception( std::make_exception_ptr( make_exception("read", ec) ) ); } }); #else // defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES) api.init_read( std::bind([]( boost::fibers::promise< std::string > & promise, AsyncAPI::errorcode ec, std::string const& data) mutable { if ( ! ec) { promise.set_value( data); } else { promise.set_exception( std::make_exception_ptr( make_exception("read", ec) ) ); } }, std::move( promise), std::placeholders::_1, std::placeholders::_2) ); #endif // BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES return future.get(); }
future::get()
will do the right thing, either returning std::string
or throwing an exception.