5. 多io_service
前面那篇讲到了多线程的用法。这篇讲一下多io_service的用法,大家可参考下官方提供的HTTP Server 2(an io_service-per-CPU)这个例子。
官方提供的例子中,使用方法很简单,建立一个io_service_pool,然后对每一个io_service开一个线程去让它跑起来(毕竟,io_service::run这个函数在有任务的时候会一直工作的,只有开多个线程才做到不影响别的io_service)。当然,我们也可以为每个io_service开多个线程,这样才不会存在上一篇中说到的多线程问题。
下面以Windows平台讨论io_service,看下io_service的构造过程在Windows下的实现
win_iocp_io_service::win_iocp_io_service( boost::asio::io_service& io_service, size_t concurrency_hint) : boost::asio::detail::service_base<win_iocp_io_service>(io_service), iocp_(), outstanding_work_(0), stopped_(0), stop_event_posted_(0), shutdown_(0), gqcs_timeout_(get_gqcs_timeout()), dispatch_required_(0) { BOOST_ASIO_HANDLER_TRACKING_INIT; iocp_.handle = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, static_cast<DWORD>(concurrency_hint < DWORD(~0) ? concurrency_hint : DWORD(~0))); if (!iocp_.handle) { DWORD last_error = ::GetLastError(); boost::system::error_code ec(last_error, boost::asio::error::get_system_category()); boost::asio::detail::throw_error(ec, "iocp"); } }
通过源码,我们可以发现每个io_service在构造的过程中,会创建一个IOCP。
创建好之后,我们就可以使用这个IOCP了,
boost::system::error_code win_iocp_io_service::register_handle( HANDLE handle, boost::system::error_code& ec) { if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0) { DWORD last_error = ::GetLastError(); ec = boost::system::error_code(last_error, boost::asio::error::get_system_category()); } else { ec = boost::system::error_code(); } return ec; }
哦,看着就这么简单。
在io_service类代码中发现add_service这么个函数
/// Add a service object to the io_service. /** * This function is used to add a service to the io_service. * * @param ios The io_service object that owns the service. * * @param svc The service object. On success, ownership of the service object * is transferred to the io_service. When the io_service object is destroyed, * it will destroy the service object by performing: * @code delete static_cast<io_service::service*>(svc) @endcode * * @throws boost::asio::service_already_exists Thrown if a service of the * given type is already present in the io_service. * * @throws boost::asio::invalid_service_owner Thrown if the service's owning * io_service is not the io_service object specified by the ios parameter. */ template <typename Service> friend void add_service(io_service& ios, Service* svc);
从注释可以看到,io_service之间可以相互转移service对象。单io_service应该不会用到这个函数吧。