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 学习(六) 定时器的更多相关文章

  1. boost asio 学习(一)io_service的基础

    原文  http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio/ 编译环境 b ...

  2. boost::asio学习(定时器)

    #include <boost/asio.hpp> #include <iostream> void handle1(const boost::system::error_co ...

  3. boost::asio 学习

    安装 下载-解压 指定安装目录 ./bootstrap.sh --prefix=/usr/local/boost_1_68_0 查看所有必须要编译才能使用的库 ./b2 --show-librarie ...

  4. boost asio 学习(九) boost::asio 网络封装

    http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio?pg=10 9. A ...

  5. boost asio 学习(八) 网络基础 二进制写发送和接收

    http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio?pg=9 8. Net ...

  6. boost asio 学习(七) 网络基础 连接器和接收器(TCP示例)

    http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio?pg=8 7. Net ...

  7. BOOST ASIO 学习专贴

    本文已于20170903更新完毕,所有boost asio 代码均为本人手抄.编译器为vs2013,并且所有代码已经上传,本文下方可下载源码 为了学习boost asio库,我是从boost的官方bo ...

  8. boost asio 学习(五) 错误处理

    http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg=6 5. Erro ...

  9. boost asio 学习(四)使用strand将任务排序

    http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg=5 4. Seri ...

随机推荐

  1. Docker镜像常用命令

    镜像(image)是Docker三大核心概念中最重要的,是运行容器的前提. Docker运行容器前需要本地存在对应的镜像,如果镜像没保存在本地,Docker会尝试先从默认镜像仓库下载(默认使用Dock ...

  2. 洛谷P1443马的遍历

    传送 这是个广搜,思路和普通的迷宫题差不多,但我卡了3遍,为什么呢? 因为输出格式 题目要求左对齐,宽度为5输出,在此说一下如何控制宽度. 下面的m都为要求的宽度 int 类型: printf: %m ...

  3. finstrument-functions

    2017-12-03 23:59:16 参考 如何快速地在每个函数入口处加入相同的语句? https://www.zhihu.com/question/56132218 做个存档 scj@scjCom ...

  4. 1、ZooKeeper 基本概念、使用方法、实践场景

    ZooKeeper 基本概念 ZooKeeper 是面向分布式应用的协调服务,其实现了树形结构的数据模型(与文件系统类似),并且提供了简洁的编程原语.ZooKeeper 能够作为基础,用于构建更高层级 ...

  5. Reachability实时监控网络变化

    Reachability是一种实时观察网络发生变化控件,如当你的手机处于WiFi情况下,他就会检测环境,当处于GPS的情况下改变环境,当处于无网络的情况下又是一种环境.下面我们看下关于Reachabi ...

  6. vue+窗格切换+田字+dicom显示_02

    环境:vue+webpack+cornerstone ide:vs code 需求:窗格设置+拼图设置 分析: 由于时间的原因,我也没有Baidu更好的显示窗格的方法,所以使用比较笨的方法,通过组件显 ...

  7. 概念吓死人的webservice

    前倾提要:这是我七拼八凑,自己用手打出来的头一篇了!都是别人的想法,我抄袭的,我坦白,我这只是总结一下觉得有用的 本来题目想叫(1)REST API 和WebService(2)REST 样式和 SO ...

  8. html 设置input框的记忆功能(联想内容)

    autocomplete=“on/off” 1.默认情况下,autocomplete的值是on.你可以将其设置为off. 2.autocomplete属性可以放在input 元素上,也可以放在form ...

  9. python3:实现字符串的全排列(有重复字符)

    抛出问题 求任意一个字符串的全排列组合,例如a='123',输出 123,132,213,231,312,321. 解决方案 #字符串任意两个位置字符交换 def str_replace(str, x ...

  10. 这可能是目前最新的 Vue 相关开源项目库汇总(转)

    访问地址:https://juejin.im/entry/58bf745fa22b9d0058895a58 原文链接:https://github.com/opendigg/awesome-githu ...