当前位置: 首页 > 知识库问答 >
问题:

Boost::ASIO与Boost::Unique_Future

元鸿波
2023-03-14

根据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个答案

孟建木
2023-03-14

boost.asio仅为异步操作提供了一流的支持,以返回一个C++11std::future或堆栈式协式中的实际值。不过,异步操作的要求说明了如何为其他类型定制返回类型,如boost.thread的boost::unique_future。它要求:

  • handler_type模板的专门化。此模板用于根据异步操作的签名确定要使用的实际处理程序。
  • async_result模板的专门化。此模板既用于确定返回类型,也用于从处理程序提取返回值。

下面是一个最小的完整示例,演示deadline_timer::async_wait()返回boost:unique_future并在由组成的一系列连续操作上执行基本计算。然后()。为了使示例简单,我选择只为示例中使用的异步操作签名指定handler_type。要获得完整的参考资料,我强烈建议查看use_future.hppimpl/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实现NAT打孔。根据我的理解,NAT穿孔器的工作原理是这样的(UDP/TCP): 客户端A绑定到端口并连接到服务器S,客户端B执行相同操作。 当S同时接收到请求和匹配时,它将A的ip和端口发送给B,B发送给A。 a和B接收对方的ip和端口,现在它们从同一端口向对方发送消息并形成连接(因为它们正在等待回复?) 如果没有成功的或,我似乎无法运行任何。当然,当目标端口没

  • epoll()可以对许多fd类型进行轮询,如普通fd、sockets、timefd、eventfd等。 Boost::ASIO::IP::TCP::Socket Boost::ASIO::IP::TCP::Acceptor Boost::ASIO::IP::UDP::Socket deadline_timer。 还有别的办法吗?

  • 问题内容: 我试图从boost :: asio运行SSL示例,并且在运行它们时遇到“无效参数”异常。我在Linux x86_64上。 http://www.boost.org/doc/libs/1_46_1/doc/html/boost_asio/example/ssl/client.cpp http://www.boost.org/doc/libs/1_46_1/doc/html/boost_a

  • Boost 库是一个经过千锤百炼、可移植、提供源代码的 C++ 库,作为标准库的后备,是 C++ 标准化进程的发动机之一。 Boost 库由 C++ 标准委员会库工作组成员发起,在 C++ 社区中影响甚大,其成员已近 2000 人。 Boost 库为我们带来了最新、最酷、最实用的技术,是不折不扣的“准”标准库。

  • 问题内容: 我目前正在尝试使用boost-asio的套接字API通过网络将一些JSON数据从客户端传输到服务器。我的客户基本上是这样做的: 在服务器端,我可以选择各种功能。我想使用JsonCpp解析接收到的数据。在研究JsonCpp API(http://jsoncpp.sourceforge.net/class_json_1_1_reader.html)时,我发现Reader可以在char数组或