关于创建boost.asio async_xxxx处理程序对象

时间:2016-09-27 02:50:11

标签: c++ c++11 boost

我正在阅读Boost.Asio源代码,但有些代码我很困惑。有没有人帮助解释更好的理解,或者我可以参考一些材料来理解?感谢。

实际代码:

// Wait until data can be received without blocking.
  template <typename Handler>
  void async_receive_from(implementation_type& impl,
      const null_buffers&, endpoint_type& sender_endpoint,
      socket_base::message_flags flags, Handler& handler)
  {
    bool is_continuation =
      boost_asio_handler_cont_helpers::is_continuation(handler);

    // Allocate and construct an operation to wrap the handler.
    typedef reactive_null_buffers_op<Handler> op;
    typename op::ptr p = { boost::asio::detail::addressof(handler),
      boost_asio_handler_alloc_helpers::allocate(
        sizeof(op), handler), 0 };
    p.p = new (p.v) op(handler);

    BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
          &impl, "async_receive_from(null_buffers)"));

    // Reset endpoint since it can be given no sensible value at this time.
    sender_endpoint = endpoint_type();

    start_op(impl,
        (flags & socket_base::message_out_of_band)
          ? reactor::except_op : reactor::read_op,
        p.p, is_continuation, false, false);
    p.v = p.p = 0;
  }

特别是:

typedef reactive_null_buffers_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
  boost_asio_handler_alloc_helpers::allocate(
    sizeof(op), handler), 0 };
p.p = new (p.v) op(handler);

感谢。

1 个答案:

答案 0 :(得分:1)

嗯..小时候看......你正试图理解async_receive_from类的reactive_socket_service函数。特别是采用null_buffer

的那个

功能的签名:

template <typename Handler>
  void async_receive_from(implementation_type& impl,
                          const null_buffers&, 
                          endpoint_type& sender_endpoint,
                          socket_base::message_flags flags, 
                          Handler& handler)

现在,null_buffers的重要性是什么?

简而言之,它基本上允许在调用的回调中执行缓冲区管理,而不是在调用async_receive_from时提供缓冲区,就像在其他重载中一样。
 有关其用例的更详细说明,请参阅THIS答案。

什么是reactive_null_buffers_op<Handler> op

由于您处于这一点,我假设您已了解asio中的operation类。简单来说,它基本上在完全执行特定操作时调用用户提供的回调。在scheduler_operation::complete中查找scheduler_operation.hpp

reactive_null_buffers_op派生自scheduler_operation(通过reactive_op),并且还存储传递给async_receive_from的处理程序的副本。实际的细节有点复杂和狡猾。现在,知道此类的do_complete方法是向处理程序的上行调用可能就足够了。

什么是typename op::ptr

ASIO_DEFINE_HANDLER_PTR中查找handler_alloc_helpers.hpp。简单来说,它是一个结构,它将处理程序传递给异步函数。 ASIO需要在堆上(或通过自定义分配器)单独分配处理程序,以确保它在套接字接收操作完成期间存在。这是以下2行:

typename op::ptr p = { boost::asio::detail::addressof(handler),
      boost_asio_handler_alloc_helpers::allocate(
        sizeof(op), handler), 0 };
    p.p = new (p.v) op(handler);

我们正在通过reactive_null_buffers_op<Handler>(第二行)在已分配的空间上创建placement new的实例。

现在是什么?

一个ASIO已经存储了用户传递的处理程序对象,它需要在套接字上启动主读取操作。为此,它调用start_op函数。 start_op的详细信息超出了所提问题的当前范围。因此,简而言之start_op最终将套接字注册到轮询器,例如epoll。现在在op中的处理程序最终会在准备执行读取操作时被调用(为此跳过了很多细节)。