boost :: asio with boost :: unique_future [英] boost::asio with boost::unique_future

查看:308
本文介绍了boost :: asio with boost :: unique_future的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 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()。如何使用?

解决方案

Boost.Asio只提供一流的异步操作支持,返回C ++ 11 std :: future stackful协同程序。不过,对异步操作的要求文档如何自定义其他类型的返回类型,例如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用于表示异步操作的类应该返回
/// boost :: unique_future。
class use_unique_future_t {};

/// @brief一个特殊值,类似于std :: nothrow。
constexpr use_unique_future_t use_unique_future;

命名空间详细信息{

/// @brief完成处理程序以适应boost :: promise作为完成
///处理程序。
template< typename T>
class unique_promise_handler;

/// @brief完成处理程序以适应void boost :: promise作为完成
///处理程序。
模板<>
class unique_promise_handler< void>
{
public:
/// @brief从use_unique_future构造特殊值。
explicit unique_promise_handler(use_unique_future_t)
:promise_(std :: make_shared< boost :: promise< void>>())
{}

void operator )(const boost :: system :: error_code& error)
{
//错误的情况下,将错误代码转换为异常并将其设置为
// promise。
if(error)
promise _-> set_exception(
std :: make_exception_ptr(boost :: system :: system_error(error)));
//否则,设置值。
else
promise _-> set_value();
}

// private:
std :: shared_ptr< boost :: promise< void> >诺言_;
};

//确保从处理程序抛出的任何异常通过未来传播回到
//调用者。
template< typename函数,typename T>
void asio_handler_invoke(
函数函数,
unique_promise_handler< T> * handler)
{
//保证函数调用期间的promise生命。
std :: shared_ptr< boost :: promise< T> > promise(handler-> promise_);
try
{
function();
}
catch(...)
{
promise-> set_exception(std :: current_exception());
}
}

} //命名空间详细信息

命名空间boost {
命名空间asio {

/ // @brief用于use_unique_future的Handler类型专门化。
template< typename ReturnType>
struct handler_type<
use_unique_future_t,
ReturnType(boost :: system :: error_code)>
{
typedef :: detail :: unique_promise_handler< void>类型;
};

/// @brief Handler traits为unique_promise_handler的专业化。
template< typename T>
class async_result< :: detail :: unique_promise_handler< T> >
{
public:
//启动函数将返回boost :: unique_future。
typedef boost :: unique_future< T>类型;

//构造函数为异步操作创建一个新的promise,并获得
//对应的future。
explicit async_result(:: detail :: unique_promise_handler< T>& handler)
{
value_ = handler.promise _-> get_future();
}

//获取从启动函数返回的未来。
type get(){return std :: move(value_); }

private:
type value_;
};

} //命名空间asio
} //命名空间boost

int main()
{
boost :: asio :: io_service io_service;
boost :: asio :: io_service ::工作工作(io_service);

//在自己的线程中运行io_service以演示将来的用法。
std :: thread thread([& io_service](){io_service.run();});

//臂3秒定时器。
boost :: asio :: deadline_timer timer(
io_service,boost :: posix_time :: seconds(3));

//异步等待计时器,然后在未来的延续期间执行基本计算
//。
boost :: unique_future< int> result =
timer.async_wait(use_unique_future)
.then([](boost :: unique_future< void> future){
std :: cout< < std :: endl;
return 21;
})
.then([](boost :: unique_future< int> future){
std :: cout< <calculation 2<<< std :: endl;
return 2 * future.get();
})
;

std :: cout<< 等待结果< std :: endl;
//等待定时器触发,并为其继续计算
//结果。
std :: cout<< result.get()<< std :: endl;

//清理。
io_service.stop();
thread.join();
}

输出:

 等待结果
计算1
计算2
42
pre>

According to http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/overview/cpp2011/futures.html, we can use boost::asio with std::future. But I couldn't find any information about working with boost::unique_future, which has more functions, such as then(). How can I use?

解决方案

Boost.Asio only provides first-class support for asynchronous operations to return a C++11 std::future or an actual value in stackful coroutines. Nevertheless, the requirements on asynchronous operations documents how to customize the return type for other types, such as Boost.Thread's boost::unique_future. It requires:

  • A specialization of the handler_type template. This template is used to determine the actual handler to use based on the asynchronous operation's signature.
  • A specialization of the async_result template. This template is used both to determine the return type and to extract the return value from the handler.

Below is a minimal complete example demonstrating deadline_timer::async_wait() returning boost:unique_future with a basic calculation being performed over a series of continuations composed with .then(). To keep the example simple, I have opted to only specialize handler_type for the asynchronous operation signatures used in the example. For a complete reference, I highly suggest reviewing use_future.hpp and 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();
}

Output:

Waiting for result
calculation 1
calculation 2
42

这篇关于boost :: asio with boost :: unique_future的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆