一、同步:定时器中执行一个阻塞等待
#include <iostream> #include <boost/asio.hpp> #include<boost/date_time/posix_time/posix_time.hpp> int main() { boost::asio::io_service io; boost::asio::deadline_timer t(io,boost::posix_time::seconds(5)); t.wait(); std::cout << "Hello, world!\n"; /* 最后我们打印出“Hello,world”信息以显示定时器已经终止。 */ return 0; }
说明:deadline_timer::wait()函数调用直到定时器终止(从定时器被创建算起,五秒后终止)才会返回。
一个deadline timer 通常是下面两种状态中的一种:"expired(终止)" 或"not expired(不终止)"。
deadline_timer::wait()函数如果被一个已经终止的定时器调用, 它将立即返回。
二、异步:
#include <iostream> #include <boost/asio.hpp> #include <boost/date_time/posix_time/posix_time.hpp> void print(const boost::system::error_code & e) /* 异步等待结束将被调用的函数 */ { std::cout << "Hello, world!\n"; } int main() { boost::asio::io_service io; boost::asio::deadline_timer t(io, boost::posix_time::seconds(5)); t.async_wait(print); /* 执行一个异步等待,并传入上面定义的print回调句柄。 */ io.run(); return 0; }
使用Asio的异步功能意味着当一个异步操作完成时一个回调函数将被调用。在本程序中我们定义一个名为“print”的函数,在异步等待结束后这个函数将被调用。
三、异步结束后,在回调函数中重启异步操作
#include <iostream> #include <boost/asio.hpp> #include <boost/bind.hpp> #include <boost/date_time/posix_time/posix_time.hpp> void print(const boost::system::error_code & e,boost::asio::deadline_timer* t, int* count) { if (*count < 5) { std::cout << *count << "\n"; ++(*count); /* 推迟定时器的终止时间。在原先的终止时间上增加延时,确保定时器不会在处理回调函数所需时间内到期 */ t->expires_at(t->expires_at() + boost::posix_time::seconds(1)); t->async_wait(boost::bind(print, boost::asio::placeholders::error, t, count)); } } int main() { boost::asio::io_service io; int count = 0; boost::asio::deadline_timer t(io, boost::posix_time::seconds(5)); /* 在第四步中,当在主函数中的调用boost::asio::deadline_timer::async_wait() 函数时, 我们绑定print函数所需要的附加参数 */ t.async_wait(boost::bind(print, boost::asio::placeholders::error, &t, &count)); io.run(); std::cout << "Final count is " << count << "\n"; return 0; }1, 使用Asio实现一个重复定时器,你必须在你的回调函数中去改变定时器的终止时间,然后开始一个新的异步等待。
四、使用类成员函数作为回调句柄。程序完成和上面完全同样的功能
#include <iostream> #include <boost/asio.hpp> #include <boost/bind.hpp> #include <boost/date_time/posix_time/posix_time.hpp> class printer { public: printer(boost::asio::io_service& io) : timer_(io, boost::posix_time::seconds(1)), count_(0) { timer_.async_wait(boost::bind(&printer::print, this)); } ~printer() { std::cout << "Final count is " << count_ << " "; } void print() { if (count_ < 5) { std::cout << count_ << " "; ++count_; timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1)); timer_.async_wait(boost::bind(&printer::print, this)); } } private: boost::asio::deadline_timer timer_; int count_; }; int main() { boost::asio::io_service io; printer p(io); io.run(); return 0; }五、使用boost::asio::strand 类来创建多线程程序中的同步回调句柄。
单线程通常是使用Asio开发应用程序最好的方式。下面是Asio在程序中的局限性,尤其是服务器方面,包括:
操作需要较长时间处理才能完成时弱响应
在大规模的多处理机系统中表现不佳
如果你发现自己陷入这些局限时,一个可供选择的方法是创建一个每个线程都调用boost::asio::io_service::run()的线程池。不过,因为这允许并发操作,当访问一个共享、非线程安全的资源时,我们需要一个同步方式。
#include <iostream> #include <boost/asio.hpp> #include <boost/thread.hpp> #include <boost/bind.hpp> #include <boost/date_time/posix_time/posix_time.hpp> class printer { public: printer(boost::asio::io_service& io) : strand_(io), timer1_(io, boost::posix_time::seconds(1)), timer2_(io, boost::posix_time::seconds(1)), count_(0) { timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this))); timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this))); } ~printer() { std::cout << "Final count is " << count_ << "\n"; } void print1() { if (count_ < 10) { std::cout << "Timer 1: " << count_ << "\n"; ++count_; timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1)); timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this))); } } void print2() { if (count_ < 10) { std::cout << "Timer 2: " << count_ << "\n"; ++count_; timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1)); timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this))); } } private: boost::asio::strand strand_; boost::asio::deadline_timer timer1_; boost::asio::deadline_timer timer2_; int count_; }; int main() { boost::asio::io_service io; printer p(io); boost::thread t(boost::bind(&boost::asio::io_service::run, &io)); io.run(); t.join(); return 0; }
1,在主函数中,boost::asio::io_service::run() 现在被两个线程调用:主线程和一个附加线程。这一切依赖于boost::thread对象来完成。正如它被一个单线程调用一样,boost::asio::io_service::run() 的并发调用会一直持续到无任何“工作”可做。后台线程直到所有异步操作都完成后才会退出。
2, 在一个多线程程序中,当访问同一共享资源时,异步操作必须是同步的。在本例中,print1和print2函数使用的共享资源为std::cout 和count_数据成员。
3, 除了初始化一对boost::asio::deadline_timer 成员变量外,构造函数还初始化一个boost::asio::strand类型的strand_成员变量。boost::asio::strand 对象保证:对于通过它来分派执行的众操作中,只有一个操作执行完成之后才允许进入下一个操作。