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秒的定时器。
#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,保持定
时器可重用。
#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。
代码如下
#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来获取灵活性和实现功能。在后面的网络系统中我们将使用这些组件。
boost asio 学习(六) 定时器的更多相关文章
- boost asio 学习(一)io_service的基础
原文 http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio/ 编译环境 b ...
- boost::asio学习(定时器)
#include <boost/asio.hpp> #include <iostream> void handle1(const boost::system::error_co ...
- boost::asio 学习
安装 下载-解压 指定安装目录 ./bootstrap.sh --prefix=/usr/local/boost_1_68_0 查看所有必须要编译才能使用的库 ./b2 --show-librarie ...
- boost asio 学习(九) boost::asio 网络封装
http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio?pg=10 9. A ...
- boost asio 学习(八) 网络基础 二进制写发送和接收
http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio?pg=9 8. Net ...
- boost asio 学习(七) 网络基础 连接器和接收器(TCP示例)
http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio?pg=8 7. Net ...
- BOOST ASIO 学习专贴
本文已于20170903更新完毕,所有boost asio 代码均为本人手抄.编译器为vs2013,并且所有代码已经上传,本文下方可下载源码 为了学习boost asio库,我是从boost的官方bo ...
- boost asio 学习(五) 错误处理
http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg=6 5. Erro ...
- boost asio 学习(四)使用strand将任务排序
http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg=5 4. Seri ...
随机推荐
- Docker镜像常用命令
镜像(image)是Docker三大核心概念中最重要的,是运行容器的前提. Docker运行容器前需要本地存在对应的镜像,如果镜像没保存在本地,Docker会尝试先从默认镜像仓库下载(默认使用Dock ...
- sql server 数据库变成单用户模式的恢复
USE master;GODECLARE @SQL VARCHAR(MAX);SET @SQL=''SELECT @SQL=@SQL+'; KILL '+RTRIM(SPID)FROM master. ...
- NodeJS client code websocket
var WebSocketClient = require('websocket').client; var client = new WebSocketClient(); client.on('co ...
- Requests对HTTPS请求验证SSL证书
SSL证书通过在客户端浏览器和Web服务器之间建立一条SSL安全通道(Secure socket layer(SSL)安全协议是由Netscape Communication公司设计开发.该安全协议主 ...
- qt4 看不到qstring内容
qt4: https://gist.github.com/gregseth/9bcd0112f8492fa7bfe7
- OpenStack Trove组件WSGI和RPC调用流程(参考调用的整个过程)
参考博文:https://blog.csdn.net/bill_xiang_/article/details/72909927
- 【亲测】解决虚拟机CentOS7联网ping不通相关问题(通俗易懂)
对于是使用windows操作系统的小伙伴来说(mac用户忽略),要学习一些技术可能需要使用Linux系统,自然就需要使用虚拟机安装Linux,当然现在很多主流的学习网站上的教程都会提供老师配置好的虚拟 ...
- spring 之 类型转换 2
spring内置的转换器 在spring xml 文件中,配置属性的时候, 不管实际是 list 还是map ,还是Date, 或者原生的java 类型, 我们只能配置xml 给它们. 那么 spri ...
- leetcode31
class Solution { public: void nextPermutation(vector<int>&nums) { int len = nums.size(); , ...
- 学习node.js 第2篇 介绍node.js 安装
Node.js - 环境安装配置 如果愿意安装设置Node.js环境,需要计算机上提供以下两个软件: 一.文本编辑器 二.Node.js二进制安装包 文本编辑器 这将用来编写程序代码. 一些编辑器包括 ...