到了这里,我们已经分析了event loop的基本流程了,接下来就要从使用者的角度来分析一下,event loop一般会管理两类时间,一类是fd的读写,还有一类是timer到期,这里先讨论fd的读写
boost asio中将fd抽象为以下几类service
datagram_socket_service:UDP socket
raw_socket_service:基本的socket
socket_acceptor_service:acceptor socket
stream_socket_service:TCP socket
每类service提供的接口都不同,我们这里只关注实现了TCP的stream_socket_service,它的接口定义可以从boost asio的文档上查到,
这里只是以async_send为例来说明一下基本的流程
stream_socket_service也是一个典型的pImpl模式,它的实现由编译选项决定
#if defined(BOOST_ASIO_HAS_IOCP)
typedef detail::win_iocp_socket_service service_impl_type;
#else
typedef detail::reactive_socket_service service_impl_type;
#endif
service_impl_type service_impl_;
对于Linux系统来说,只关注reactive_socket_service,这里的Protocol的要求文档在这里
在reactive_socket_service中对service提供的各种接口提供了实现,以async_send为例
template
class send_op_base : public reactor_op
{
public:
send_op_base(socket_type socket, const ConstBufferSequence& buffers,
socket_base::message_flags flags, func_type complete_func)
: reactor_op(&send_op_base::do_perform, complete_func),
socket_(socket),
buffers_(buffers),
flags_(flags)
{
}
// 实际执行send操作的地方
static bool do_perform(reactor_op* base)
{
send_op_base* o(static_cast(base));
buffer_sequence_adapter bufs(o->buffers_);
for (;;)
{
// Send the data.
boost::system::error_code ec;
int bytes = socket_ops::send(o->socket_,
bufs.buffers(), bufs.count(), o->flags_, ec);
// Retry operation if interrupted by signal.
if (ec == boost::asio::error::interrupted)
continue;
// Check if we need to run the operation again.
if (ec == boost::asio::error::would_block
|| ec == boost::asio::error::try_again)
return false;
o->ec_ = ec;
o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
return true;
}
}
private:
socket_type socket_;
ConstBufferSequence buffers_;
socket_base::message_flags flags_;
};
class send_op : public send_op_base
{
public:
send_op(socket_type socket, const ConstBufferSequence& buffers,
socket_base::message_flags flags, Handler handler)
: send_op_base(socket,
buffers, flags, &send_op::do_complete),
handler_(handler)
{
}
// send完成后调用async_send(const ConstBufferSequence & buffers, WriteHandler handler)中传入的handler回调函数
// 在这里实现proactor模式
static void do_complete(io_service_impl* owner, operation* base,
boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
{
// Take ownership of the handler object.
send_op* o(static_cast(base));
typedef handler_alloc_traits alloc_traits;
handler_ptr ptr(o->handler_, o);
// Make the upcall if required.
if (owner)
{
// Make a copy of the handler so that the memory can be deallocated
// before the upcall is made. Even if we're not about to make an
// upcall, a sub-object of the handler may be the true owner of the
// memory associated with the handler. Consequently, a local copy of
// the handler is required to ensure that any owning sub-object remains
// valid until after we have deallocated the memory here.
detail::binder2
handler(o->handler_, o->ec_, o->bytes_transferred_);
ptr.reset();
boost::asio::detail::fenced_block b;
boost_asio_handler_invoke_helpers::invoke(handler, handler);
}
}
private:
Handler handler_;
};
template
void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
socket_base::message_flags flags, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
// 将send_op封装好
typedef send_op value_type;
typedef handler_alloc_traits alloc_traits;
raw_handler_ptr raw_ptr(handler);
handler_ptr ptr(raw_ptr,
impl.socket_, buffers, flags, handler);
// 将send_op放到socket中的write_op对应的queue中
start_op(impl, reactor::write_op, ptr.get(), true,
(impl.protocol_.type() == SOCK_STREAM
&& buffer_sequence_adapter::all_empty(buffers)));
ptr.release();
}