boost asio 学习(六) 定时器
http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-
started-with-boostasio?pg=7
6 定时器
boost::asio 提供了一个 deadline_timer class来提供同步与异步的接口。
BOOST文档提供了一组优秀示例。
第一个例子,将创建一个间隔5秒的定时器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | #include <boost/asio.hpp> #include <boost/shared_ptr.hpp> #include <boost/thread.hpp> #include <boost/thread/mutex.hpp> #include <boost/bind.hpp> #include <iostream> boost::mutex global_stream_lock; void WorkerThread(boost::shared_ptr< boost::asio::io_service > io_service) { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Thread Start" << std::endl; global_stream_lock.unlock(); while ( true ) { try { boost::system::error_code ec; io_service->run(ec); if (ec) { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Error: " << ec << std::endl; global_stream_lock.unlock(); } break ; } catch (std::exception & ex) { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Exception: " << ex.what() << std::endl; global_stream_lock.unlock(); } } global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Thread Finish" << std::endl; global_stream_lock.unlock(); } void TimerHandler( const boost::system::error_code & error) { if (error) { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Error: " << error << std::endl; global_stream_lock.unlock(); } else { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] TimerHandler " << std::endl; global_stream_lock.unlock(); } } int main( int argc, char * argv[]) { boost::shared_ptr< boost::asio::io_service > io_service( new boost::asio::io_service ); boost::shared_ptr< boost::asio::io_service::work > work( new boost::asio::io_service::work(*io_service) ); global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Press [return] to exit." << std::endl; global_stream_lock.unlock(); boost::thread_group worker_threads; for ( int x = 0; x < 2; ++x) { worker_threads.create_thread(boost::bind (&WorkerThread, io_service)); } boost::asio::deadline_timer timer(*io_service); timer.expires_from_now(boost::posix_time::seconds(5)); timer.async_wait(TimerHandler); std::cin. get (); io_service->stop(); worker_threads.join_all(); return 0; } |
如果我们想创建一个可冲用的定时器.我们将定时器对象设置为全局,但是可能
导致共享对象不是线程安全的。boost::bind能解决这个问题。使用定时器对象
的shared_ptr指针,我们能使用bind并且传递定时器到指定的handler,保持定
时器可重用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | #include <boost/asio.hpp> #include <boost/shared_ptr.hpp> #include <boost/thread.hpp> #include <boost/thread/mutex.hpp> #include <boost/bind.hpp> #include <iostream> boost::mutex global_stream_lock; void WorkerThread(boost::shared_ptr< boost::asio::io_service > io_service) { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Thread Start" << std::endl; global_stream_lock.unlock(); while ( true ) { try { boost::system::error_code ec; io_service->run(ec); if (ec) { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Error: " << ec << std::endl; global_stream_lock.unlock(); } break ; } catch (std::exception & ex) { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Exception: " << ex.what() << std::endl; global_stream_lock.unlock(); } } global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Thread Finish" << std::endl; global_stream_lock.unlock(); } void TimerHandler( const boost::system::error_code & error, boost::shared_ptr< boost::asio::deadline_timer > timer ) { if (error) { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Error: " << error << std::endl; global_stream_lock.unlock(); } else { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] TimerHandler " << std::endl; global_stream_lock.unlock(); timer->expires_from_now(boost::posix_time::seconds (5)); timer->async_wait(boost::bind(&TimerHandler, _1, timer)); } } int main( int argc, char * argv[]) { boost::shared_ptr< boost::asio::io_service > io_service( new boost::asio::io_service ); boost::shared_ptr< boost::asio::io_service::work > work( new boost::asio::io_service::work(*io_service) ); global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Press [return] to exit." << std::endl; global_stream_lock.unlock(); boost::thread_group worker_threads; for ( int x = 0; x < 2; ++x) { worker_threads.create_thread(boost::bind (&WorkerThread, io_service)); } boost::shared_ptr< boost::asio::deadline_timer > timer( new boost::asio::deadline_timer(*io_service) ); timer->expires_from_now(boost::posix_time::seconds(5)); timer->async_wait(boost::bind(&TimerHandler, _1, timer)); std::cin. get (); io_service->stop(); worker_threads.join_all(); return 0; } |
使用bind可以做许多有趣的事情,_1参数是一个占位符。因为TimerHandler 函
数需要一个参数用于回调,我们需要引用这个bind调用。_1意味着第一个参数,
我们稍后提供。
运行上面例子,我们将获得一个每五秒激活一次的定时器。
如果想保证定时器不和work处理器同时运行,我们可以使用strand。
代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | #include <boost/asio.hpp> #include <boost/shared_ptr.hpp> #include <boost/thread.hpp> #include <boost/thread/mutex.hpp> #include <boost/bind.hpp> #include <iostream> boost::mutex global_stream_lock; void WorkerThread(boost::shared_ptr< boost::asio::io_service > io_service) { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Thread Start" << std::endl; global_stream_lock.unlock(); while ( true ) { try { boost::system::error_code ec; io_service->run(ec); if (ec) { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Error: " << ec << std::endl; global_stream_lock.unlock(); } break ; } catch (std::exception & ex) { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Exception: " << ex.what() << std::endl; global_stream_lock.unlock(); } } global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Thread Finish" << std::endl; global_stream_lock.unlock(); } void TimerHandler( const boost::system::error_code & error, boost::shared_ptr< boost::asio::deadline_timer > timer, boost::shared_ptr< boost::asio::io_service::strand > strand ) { if (error) { global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Error: " << error << std::endl; global_stream_lock.unlock(); } else { std::cout << "[" << boost::this_thread::get_id() << "] TimerHandler " << std::endl; timer->expires_from_now(boost::posix_time::seconds(1)); timer->async_wait( strand->wrap(boost::bind(&TimerHandler, _1, timer, strand)) ); } } void PrintNum( int x) { std::cout << "[" << boost::this_thread::get_id() << "] x: " << x << std::endl; boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); } int main( int argc, char * argv[]) { boost::shared_ptr< boost::asio::io_service > io_service( new boost::asio::io_service ); boost::shared_ptr< boost::asio::io_service::work > work( new boost::asio::io_service::work(*io_service) ); boost::shared_ptr< boost::asio::io_service::strand > strand( new boost::asio::io_service::strand(*io_service) ); global_stream_lock. lock (); std::cout << "[" << boost::this_thread::get_id() << "] Press [return] to exit." << std::endl; global_stream_lock.unlock(); boost::thread_group worker_threads; for ( int x = 0; x < 2; ++x) { worker_threads.create_thread(boost::bind(&WorkerThread, io_service)); } boost::this_thread::sleep(boost::posix_time::seconds(1)); strand->post(boost::bind(&PrintNum, 1)); strand->post(boost::bind(&PrintNum, 2)); strand->post(boost::bind(&PrintNum, 3)); strand->post(boost::bind(&PrintNum, 4)); strand->post(boost::bind(&PrintNum, 5)); boost::shared_ptr< boost::asio::deadline_timer > timer( new boost::asio::deadline_timer(*io_service) ); timer->expires_from_now(boost::posix_time::seconds(1)); timer->async_wait( strand->wrap(boost::bind(&TimerHandler, _1, timer, strand)) ); std::cin. get (); io_service->stop(); worker_threads.join_all(); return 0; } |
我们需要使用strand封装定时器处理器,strand能确保工作对象先运行而后定时器线程后运行。
本章节我们学习如何使用bind strand shard_ptr来获取灵活性和实现功能。在后面的网络系统中我们将使用这些组件。
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力


【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话