...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
The AsyncAPI::init_write()
callback passes only an errorcode
.
If we simply want the blocking wrapper to return that errorcode
,
this is an extremely straightforward use of promise<>
and
future<>
:
AsyncAPI::errorcode write_ec( AsyncAPI & api, std::string const& data) { boost::fibers::promise< AsyncAPI::errorcode > promise; boost::fibers::future< AsyncAPI::errorcode > future( promise.get_future() ); // In general, even though we block waiting for future::get() and therefore // won't destroy 'promise' until promise::set_value() has been called, we // are advised that with threads it's possible for ~promise() to be // entered before promise::set_value() has returned. While that shouldn't // happen with fibers::promise, a robust way to deal with the lifespan // issue is to bind 'promise' into our lambda. Since promise is move-only, // use initialization capture. #if ! defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES) api.init_write( data, [promise=std::move( promise)]( AsyncAPI::errorcode ec) mutable { promise.set_value( ec); }); #else // defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES) api.init_write( data, std::bind([](boost::fibers::promise< AsyncAPI::errorcode > & promise, AsyncAPI::errorcode ec) { promise.set_value( ec); }, std::move( promise), std::placeholders::_1) ); #endif // BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES return future.get(); }
All we have to do is:
promise<>
of correct type.
future<>
.
promise::set_value()
.
future::get()
.
Note | |
---|---|
This tactic for resuming a pending fiber works even if the callback is
called on a different thread than the one on which the initiating fiber
is running. In fact, the
example program’s dummy |