使用asio的过程中,一个神奇的地方就是io_service能够多线程调用。和之前的muduo库中,oneloop onethread的思想下不太相同。现在的服务器中,io一般只需要一个线程通通搞定,但是计算却需要很多线程保证并发度。所以学习了下asio中如何多个线程,一个loop。其实思想上来说,就是task queue + 多线程,task queue需要不断地加入task和给出task,这就需要加锁。也就是使用了生产消费者模型。
具体来看,消费者端:
task_io_service是非win平台下io_service的impl实现,当io_service->run的时候,就是调用了task_io_service::run
std::size_t task_io_service::run(boost::system::error_code& ec)
{
ec = boost::system::error_code();
if (outstanding_work_ == 0)
{
stop();
return 0;
}
thread_info this_thread;
this_thread.private_outstanding_work = 0;
thread_call_stack::context ctx(this, this_thread);
mutex::scoped_lock lock(mutex_);
std::size_t n = 0;
for (; do_run_one(lock, this_thread, ec); lock.lock())
if (n != (std::numeric_limits<std::size_t>::max)())
++n;
return n;
}
其中do_run_one的实现如下:
std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock,
task_io_service::thread_info& this_thread,
const boost::system::error_code& ec)
{
while (!stopped_)
{
if (!op_queue_.empty())
{
// Prepare to execute first handler from queue.
operation* o = op_queue_.front();
op_queue_.pop();
bool more_handlers = (!op_queue_.empty());
if (o == &task_operation_)
{
task_interrupted_ = more_handlers;
if (more_handlers && !one_thread_)
wakeup_event_.unlock_and_signal_one(lock);
else
lock.unlock();
task_cleanup on_exit = { this, &lock, &this_thread };
(void)on_exit;
// Run the task. May throw an exception. Only block if the operation
// queue is empty and we're not polling, otherwise we want to return
// as soon as possible.