boost::asio 与 boost::unique_future
Posted
技术标签:
【中文标题】boost::asio 与 boost::unique_future【英文标题】:boost::asio with boost::unique_future 【发布时间】:2014-04-20 21:47:34 【问题描述】:根据http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/overview/cpp2011/futures.html,我们可以将 boost::asio 与std::future
一起使用。但是我找不到任何有关使用boost::unique_future
的信息,它具有更多功能,例如then()
。如何使用?
【问题讨论】:
【参考方案1】:Boost.Asio 只为异步操作提供一流的支持以返回 C++11 std::future
或 stackful coroutines 中的实际值。尽管如此,requirements on asynchronous operations 记录了如何自定义其他类型的返回类型,例如 Boost.Thread 的boost::unique_future
。它需要:
handler_type
模板的特化。此模板用于根据异步操作的签名确定要使用的实际处理程序。
async_result
模板的特化。此模板用于确定返回类型并从处理程序中提取返回值。
下面是一个最小的完整示例,演示了deadline_timer::async_wait()
返回boost:unique_future
,并对由.then()
组成的一系列延续执行基本计算。为了使示例简单,我选择仅将 handler_type
专门用于示例中使用的异步操作签名。要获得完整的参考,我强烈建议查看 use_future.hpp
和 impl/use_future.hpp
。
#include <exception> // current_exception, make_exception_ptr
#include <memory> // make_shared, shared_ptr
#include <thread> // thread
#include <utility> // move
#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread/future.hpp>
/// @brief Class used to indicate an asynchronous operation should return
/// a boost::unique_future.
class use_unique_future_t ;
/// @brief A special value, similiar to std::nothrow.
constexpr use_unique_future_t use_unique_future;
namespace detail
/// @brief Completion handler to adapt a boost::promise as a completion
/// handler.
template <typename T>
class unique_promise_handler;
/// @brief Completion handler to adapt a void boost::promise as a completion
/// handler.
template <>
class unique_promise_handler<void>
public:
/// @brief Construct from use_unique_future special value.
explicit unique_promise_handler(use_unique_future_t)
: promise_(std::make_shared<boost::promise<void> >())
void operator()(const boost::system::error_code& error)
// On error, convert the error code into an exception and set it on
// the promise.
if (error)
promise_->set_exception(
std::make_exception_ptr(boost::system::system_error(error)));
// Otherwise, set the value.
else
promise_->set_value();
//private:
std::shared_ptr<boost::promise<void> > promise_;
;
// Ensure any exceptions thrown from the handler are propagated back to the
// caller via the future.
template <typename Function, typename T>
void asio_handler_invoke(
Function function,
unique_promise_handler<T>* handler)
// Guarantee the promise lives for the duration of the function call.
std::shared_ptr<boost::promise<T> > promise(handler->promise_);
try
function();
catch (...)
promise->set_exception(std::current_exception());
// namespace detail
namespace boost
namespace asio
/// @brief Handler type specialization for use_unique_future.
template <typename ReturnType>
struct handler_type<
use_unique_future_t,
ReturnType(boost::system::error_code)>
typedef ::detail::unique_promise_handler<void> type;
;
/// @brief Handler traits specialization for unique_promise_handler.
template <typename T>
class async_result< ::detail::unique_promise_handler<T> >
public:
// The initiating function will return a boost::unique_future.
typedef boost::unique_future<T> type;
// Constructor creates a new promise for the async operation, and obtains the
// corresponding future.
explicit async_result(::detail::unique_promise_handler<T>& handler)
value_ = handler.promise_->get_future();
// Obtain the future to be returned from the initiating function.
type get() return std::move(value_);
private:
type value_;
;
// namespace asio
// namespace boost
int main()
boost::asio::io_service io_service;
boost::asio::io_service::work work(io_service);
// Run io_service in its own thread to demonstrate future usage.
std::thread thread([&io_service]() io_service.run(); );
// Arm 3 second timer.
boost::asio::deadline_timer timer(
io_service, boost::posix_time::seconds(3));
// Asynchronously wait on the timer, then perform basic calculations
// within the future's continuations.
boost::unique_future<int> result =
timer.async_wait(use_unique_future)
.then([](boost::unique_future<void> future)
std::cout << "calculation 1" << std::endl;
return 21;
)
.then([](boost::unique_future<int> future)
std::cout << "calculation 2" << std::endl;
return 2 * future.get();
)
;
std::cout << "Waiting for result" << std::endl;
// Wait for the timer to trigger and for its continuations to calculate
// the result.
std::cout << result.get() << std::endl;
// Cleanup.
io_service.stop();
thread.join();
输出:
Waiting for result
calculation 1
calculation 2
42
【讨论】:
以上是关于boost::asio 与 boost::unique_future的主要内容,如果未能解决你的问题,请参考以下文章
std::bind 是不是应该与 boost::asio 兼容?
使用 boost::asio::async_wait_until 和 boost::asio::streambuf
将 fork() 与 boost::asio::ip::tcp::iostream 一起使用是不是安全?