boost的文档很全,两天时间看完tutorial,熟悉asio编程的基本套路。
所有代码可以参考http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/tutorial.html
或者https://github.com/NearXdu/AsioLearn
有几个注意的地方:
1.shared_ptr来管理Tcp_Connection对象
在tutorial_daytime3中有如下语句
boost::asio::async_write(socket_,boost::asio::buffer(message_),
boost::bind(&tcp_connection::handle_write,
shared_from_this(),//ensure the life tiem of the obj
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
首先shared_from_this()要保证当前的class继承于enable_shared_from_this
shared_ptr使得内存管理变得简单。
通过将shared_ptr绑定到异步操作中,首先保证对象的生命周期可以延长到异步调用结束;并且当io_service析构时,所有的shared_ptr引用将被销毁。
参考:http://stackoverflow.com/questions/3629557/boost-shared-from-this
the boost::asio::io_service destructor documentation explains it fairly well
The destruction sequence described above permits programs to simplify their resource management by using shared_ptr<>. Where an object’s lifetime is tied to the lifetime of a connection (or some other sequence of asynchronous operations), a shared_ptr to the object would be bound into the handlers for all asynchronous operations associated with it. This works as follows:
When a single connection ends, all associated asynchronous operations complete. The corresponding handler objects are destroyed, and all shared_ptr references to the objects are destroyed.
To shut down the whole program, the io_service function stop() is called to terminate any run() calls as soon as possible. The io_service destructor defined above destroys all handlers, causing all shared_ptr references to all connection objects to be destroyed.
Typically your objects will chain asynchronous operations where the handlers are bound to member functions using boost::bind and boost::shared_from_this(). There are some examples that use this concept.
2. 序列化异步操作
详见tutorial_timer5
我们知道io_service是 proactor的抽象,用来调用Asynchronous Event Demultiplexer,以及分派与事件相关的处理程序。
首先,在一个线程中至少有一个io_service对象,并且异步事件的调用是在io_service::run所在的线程,除此之外,我们的程序还可以有如下可能:
1.单线程但io_service对象
2.多线程单io_service对象
3.多线程多io_service对象
当出现多线程单io_service对象时,可以通过strand+wrap使得异步操作序列化,例如:
timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));
timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));
//其中异步完成回调
void print1()
{
if (count_ < 10)
{
//std::cout << "Timer 1: " << count_ << std::endl;
std::cout<<"Timer 1 "<<"myThreadId is "<<getThreadId()<<std::endl;
++count_;
timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1));
//timer1_.async_wait(boost::bind(&printer::print1, this));
timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));
}
}
void print2()
{
if (count_ < 10)
{
//std::cout << "Timer 2: " << count_ << std::endl;
std::cout<<"Timer 2 "<<"myThreadId is "<<getThreadId()<<std::endl;
++count_;
timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1));
// timer2_.async_wait(boost::bind(&printer::print2, this));
timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));
}
}
运行程序,将看到,分别在不同线程调用的io_service::run会先完成time1和time2两个异步事件再进入另一个线程:
如果不使用会出现如下情况:
线程就切来切去了,在boost文档中,用chain这个单词,表示异步操作被串起来依次执行。
3.参考
1.http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/tutorial.html
2.http://blog.youkuaiyun.com/mmoaay/article/details/43759703
本文介绍了Boost.Asio的核心概念及编程技巧,包括使用shared_ptr管理Tcp_Connection对象以简化资源管理,序列化异步操作的方法,以及如何在多线程环境中有效使用单个io_service实例。
4047

被折叠的 条评论
为什么被折叠?



