我正在阅读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);
感谢。
答案 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
中的处理程序最终会在准备执行读取操作时被调用(为此跳过了很多细节)。