Asio源码分析(2):Asio用到的C++技巧和优化
文章目录
Asio中用到了一些C++技巧和优化,第一次阅读源码时可能会有一些困惑(confuse)。这篇文章先简单介绍其中的一小部分,方便后面的分析。
使用析构函数执行清理操作
Asio使用对象的析构函数在作用域结束时执行一些清理操作,有点类似于Go语言中的defer
。
例如,Asio会维护一个线程间共享的Operation Queue,Asio还维护一个线程私有的Operation Queue,在运行时会先把已完成的Operation放到私有队列中,最后再将私有的Operation Queue中的Operation转移到共享的Operation Queue中:
struct scheduler::task_cleanup {
~task_cleanup() {
if (this_thread_->private_outstanding_work > 0) {
asio::detail::increment(
scheduler_->outstanding_work_,
this_thread_->private_outstanding_work);
}
this_thread_->private_outstanding_work = 0;
// Enqueue the completed operations and reinsert the task at the end of
// the operation queue.
lock_->lock();
scheduler_->task_interrupted_ = true;
scheduler_->op_queue_.push(this_thread_->private_op_queue);
scheduler_->op_queue_.push(&scheduler_->task_operation_);
}
scheduler* scheduler_;
mutex::scoped_lock* lock_;
thread_info* this_thread_;
};
该struct使用于(忽略了一些无关代码):
std::size_t scheduler::do_run_one(mutex::scoped_lock& lock,
scheduler::thread_info& this_thread,
const asio::error_code& ec) {
while (!stopped_) {
if (!op_queue_.empty()) {
// Prepare to execute first handler from queue.
operation* o = op_queue_.front();
op_queue_.pop();
// ...
if (o == &task_operation_) {
// ...
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.
task_->run(more_handlers ? 0 : -1, this_thread.private_op_queue);
} else {
// ...
}
} else {
// ...
}
}
return 0;
}
其实这里不使用析构函数能也实现同样的行为,但Asio中普遍使用了析构函数来执行清理工作。
使用模板元编程模拟概念
在C++20中,我们可以通过概念(Concepts)对模板实参做出约束。但在C++20之前没