#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <string>
using namespace boost::asio;
void PrintSomething(const std::string& msg) {
std::cout << msg << '\n';
}
void PrintHello() {
std::cout << "Hello\n";
}
int main() {
io_service service;
service.post(PrintHello);
service.post(boost::bind(PrintSomething, "whoami"));
//service.run_one();
service.run();
return 0;
}
PrintHello函数的类型为void (*)();
template <typename Handler>
void post(Handler handler)
{
// Allocate and construct an operation to wrap the handler.
// 生成handle_wrapper<void (*)()>对象,返回指向handle_wrapper<void (*)()>对象的指针
// 并将对象的所有权转移给scoped_ptr智能指针对象
// 该智能指针对象如果在生命周期内没有将对象的所有权转移则会在析构时删除其所指向的对象
handler_queue::scoped_ptr ptr(handler_queue::wrap(handler));
boost::asio::detail::mutex::scoped_lock lock(mutex_);
// If the service has been shut down we silently discard the handler.
if (shutdown_)
return;
// Add the handler to the end of the queue.
// handle_queue_与ptr对象同时持有指向handle_wrapper<void (*)()>对象的指针
handler_queue_.push(ptr.get());
// 将scoped_ptr对象对指针的所有权转移给handler_queue_,保证其析构时不会释放原来其指向的对象
ptr.release();
// An undelivered handler is treated as unfinished work.
++outstanding_work_;
// Wake up a thread to execute the handler.
if (!interrupt_one_idle_thread(lock))
{
if (!task_interrupted_ && task_)
{
task_interrupted_ = true;
task_->interrupt();
}
}
}
post方法中调用handle_queue::wrap(handler)时,编译器会根据模板方法生成新的实例方法:
template<>
static handler* wrap(void (*)() h) {
typedef handle_wrapper<void (*)()> value_type;
typedef handle_alloc_traits<void (*)(), handle_wrapper<void (*)()> > alloc_traits;
//下面的操作将new操作分成了两步:分配新建对象所需空间,构造对象并与空间关联(将对象分布到上一步所建的空间中);
// 实际上C++中的new操作都是分成这两步。
//为handle_wrapper<void (*)()>对象分配存储空间
raw_handler_ptr<alloc_traits> raw_ptr(h);
//调用handle_wrapper<void (*)()>构造函数创建对象且存储到上一步分配的空间中,并将对象的所有权转移支handler_ptr
handler_ptr<alloc_traits> ptr(raw_ptr, h);
//返回对象指针并将对象的所有权转移给wrap调用者
return ptr.release();
//如果不进行这一系列的所有权转移,新生成的对象将在raw_handler_ptr或handler_ptr对象析构时释放
}
handler_alloc_traits的定义:
template <typename Handler, typename Object>
struct handler_alloc_traits
{
typedef Handler handler_type; //函数指针对象类型
typedef Object value_type; //要创建的对象类型
typedef Object* pointer_type; //指向创建对象的指针类型
BOOST_STATIC_CONSTANT(std::size_t, value_size = sizeof(Object)); //需要创建对象的大小
};
task_io_service对象作为io_service平台相关的服务提供与平台相关的run,run_one,poll,poll_one方法,其中都调用了do_one这个方法:
// do_one方法所做的主要工作:
// 通过平台相关的系统调用(如:epoll,select)等对关心的事件进行监控
// 当关心的事件发生且处理完成,则调用其回调函数
size_t do_one(boost::asio::detail::mutex::scoped_lock& lock,
idle_thread_info* this_idle_thread, boost::system::error_code& ec)
{
// 如果没有未完成的工作并且service没有被用户叫停,则立即返回,结束事件循环
// outstanding_work_(未完成的工作)由两种类型:一种是由io_service::work封装的工作(read, write, timer);另一种是回调
if (outstanding_work_ == 0 && !stopped_)
{
stop_all_threads(lock);
ec = boost::system::error_code();
return 0;
}
//是否采用轮询机制
bool polling = !this_idle_thread;
bool task_has_run = false;
while (!stopped_)
{
// 处理器队列不为空,处理器队列中保存两种类型的handler:
// 一种task_handler_,在适当的时候被加入到处理器队列,用于表示是否需要进行事件监控;
// 另一种则是事件的回调
if (!handler_queue_.empty())
{
// Prepare to execute first handler from queue.
// 准备执行处理器队列中的第一个处理器
handler_queue::handler* h = handler_queue_.front();
// 将取出的处理器从处理器队列中移除
handler_queue_.pop();
// 如果处理器为task_handler_,表示需要进行事件监控处理
if (h == &task_handler_)
{
// 处理器队列中是否有其它的处理器
bool more_handlers = (!handler_queue_.empty());
task_interrupted_ = more_handlers || polling;
// If the task has already run and we're polling then we're done.
if (task_has_run && polling)
{
task_interrupted_ = true;
handler_queue_.push(&task_handler_);
ec = boost::system::error_code();
return 0;
}
task_has_run = true;
lock.unlock();
task_cleanup c(lock, *this);
// Run the task. May throw an exception. Only block if the handler
// queue is empty and we have an idle_thread_info object, otherwise
// we want to return as soon as possible.
// 运行事件监控,参数表示是否阻塞当前线程
task_->run(!more_handlers && !polling);
}
else
{
lock.unlock();
handler_cleanup c(lock, *this);
// Invoke the handler. May throw an exception.
// 调用事件回调函数
h->invoke(); // invoke() deletes the handler object
ec = boost::system::error_code();
return 1;
}
}
else if (this_idle_thread)
{
// Nothing to run right now, so just wait for work to do.
this_idle_thread->next = first_idle_thread_;
first_idle_thread_ = this_idle_thread;
this_idle_thread->wakeup_event.clear(lock);
this_idle_thread->wakeup_event.wait(lock);
}
else
{
ec = boost::system::error_code();
return 0;
}
}
ec = boost::system::error_code();
return 0;
}