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. 使用pageoffice进行多个文档的合并

    提前给test模板文件中 手动插入一个书签,因为pageoffice必须有一个书签后,才能在后台进行书签的创建 //多个word文件进行合并 string strCopyFolder = System ...

  2. [蓝桥杯]ALGO-181.算法训练_According to Bartjens

    问题描述 计算器和计算机的大量普及也有其弊端.即便是受过专业技术训练的学生们也很可能缺乏计算能力.由于电脑的大量使用,很多人无法心算出7*8这样的算式,甚至是用纸和笔也算不出13*.不过谁在意呢? B ...

  3. can't access lexical declaration `a' before initialization

    <script type="text/javascript"> alert(a); let a=2; </script> 以上代码报错:   Referen ...

  4. jmeter分布式、linux运行

    一.jmeter分布式压测(多台电脑一起压测) 1.有多台电脑,每台电脑上都有jmeter,而且这几台电脑都互相能ping通 2.在我的电脑的jmeter,bin目录下,修改jmeter.proper ...

  5. 转的,具体 https://www.cnblogs.com/icyJ/p/FreeShare.html

    网络资源下载网址 屏幕录像.图像处理,汉化和破解版本很新.国内破解汉化:大眼仔旭 http://www.dayanzai.me/ 开发工具,系统,数据库 http://msdn.itellyou.cn ...

  6. Linux系统重置root用户密码

    Linux系统重置root用户密码 作者:Eric 微信:loveoracle11g 查看系统版本是不是RHEL7 [root@zhouwanchun ~]# cat /etc/redhat-rele ...

  7. processjs Documentation

    Documentation   Paul Nieuwelaar edited this page on 20 Sep 2017 · 4 revisions Installation & Usa ...

  8. Java备份文件

    文件名后面补时间: public static void initFile(String sPath) { SimpleDateFormat df = new SimpleDateFormat(&qu ...

  9. [UnityAPI]SerializedObject类 & SerializedProperty类

    以Image类为例 1.MyImage.cs using UnityEngine; using UnityEngine.UI; public class MyImage : Image { ; pro ...

  10. Shell脚本1-20例

    1.每天生成一个文件 描述:请按照这样的日期格式(xxxx-xx-xx)每日生成一个文件,例如今天生成的文件为)2017-07-05.log, 并且把磁盘的使用情况写到到这个文件中,(不用考虑cron ...