boost::asio 定时器

转:http://blog.csdn.net/gubenpeiyuan/article/details/8013221

boost::asio 定时器 - boost中文文档
boost::asio - boost中文文档

所有的 asio 类都只要包含头文件:   "asio.hpp"



例子1:   使用一个同步的定时器


#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>   //使用时间间隔

int main()
{
//所有使用 asio 的程序都必须至少拥有一个 io_service 类型的对象. 
//它提供 I/O 功能. 
boost::asio::io_service io;

//创建一个定时器 deadline_timer 的对象. 
//这种定时器有两种状态: 超时 和 未超时.
//在超时的状态下. 调用它的 wait() 函数会立即返回. 
//在未超时的情况下则阻塞. 直到变为超时状态.
//它的构造函数参数为: 一个 io_service 对象(asio中主要提供IO的类都用io_service对象做构造函数第一个参数).
//                     超时时间.
//从创建开始. 它就进入 "未超时"状态. 且持续指定的时间. 转变到"超时"状态.
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));

//这里等待定时器 t 超时. 所以会阻塞5秒.
t.wait();

std::cout << "Hello, world!\n";

return 0;
}

 例子2: 使用一个异步的定时器

//一个将被定时器异步调用的函数. 
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));
//和例子1不同. 这里调用 async_wait() 执行一个异步的等待. 它注册一个可执行体(即此处的print函数).   //这里不懂的是: print的参数怎么传入?
//实际上. 这个执行体被注册到 deadline_timer 类的 io_service 成员上(即本例的 io 对象). 只有在以后调用 io.run() 时这些注册的执行体才会被真正执行.
t.async_wait(print);

//调用 io对象的 run() 函数执行那些被注册的执行体. 
//这个函数不会立即返回. 除非和他相关的定时器对象超时并且在定时器超时后执行完所有注册的执行体. 之后才返回. 
//所以它在这里阻塞一会儿. 等t超时后执行完print. 才返回.
//这里要注意的是. 调用 io.run() 可以放在其它线程中. 那样所有的回调函数都在别的线程上运行.
io.run();

return 0;
}

 

例子3: 向超时回调函数绑定参数


// 这个例子中. 每次 定时器超时后. 都修改定时器的状态到"未超时". 再注册回调函数. 这样循环 5 次. 所以 print 会被执行 5 次.

void print(const boost::system::error_code& /*e*/,
    boost::asio::deadline_timer* t, int* count)
{
if (*count < 5)
{
    std::cout << *count << "\n";
    ++(*count);
    //可以用 deadline_timer::expires_at() 来 获取/设置 超时的时间点. 
    //在这里我们将超时的时间点向后推迟一秒. 
    t->expires_at(t->expires_at() + boost::posix_time::seconds(1));

    //再次向 t 中的 io_service 对象注册一个回掉函数. 
    // 注意这里绑定时. 指定了绑定到 print 的第一个参数为: boost::asio::placeholders::error //不懂. 这个error是什么东西. 为什么在例子2中不要绑定它?
    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(1));
t.async_wait(boost::bind(print,
        boost::asio::placeholders::error, &t, &count));

io.run();

std::cout << "Final count is " << count << "\n";

return 0;
}


例子5: 多线程处理定时器的回掉函数. 同步的问题.

前面的例子都只在一个线程中调用 boost::asio::io_service::run() 函数. 
向定时器注册的回掉函数都是在调用该 run() 的线程中执行.

但实际上这个 run() 函数可以在多个线程中同时被调用. 例如:

boost::asio::io_service io; 
//两个定时器
boost::asio::deadline_timer t1(io, boost::posix_time::seconds(1));
t1.async_wait(func1);   
boost::asio::deadline_timer t2(io, boost::posix_time::seconds(1));
t2.async_wait(func2); 
由于向 io 注册了多个cmd. 这里为了效率我们想让这些cmd并行执行:
boost::thread thread1(bind(&boost::asio::io_service::run, &io);
boost::thread thread2(bind(&boost::asio::io_service::run, &io);
thread1.join();
thread2.join();

这里在多个线程中调用 io.run() 所以我们注册的cmd可能在任何一个线程中运行. 
这些线程会一直等待io对象相关的定时器超时并执行相关的 cmd. 直到所有的定时器都超时. run函数才返回. 线程才结束.

但这里有一个问题: 我们向定时器注册的 func1 和 func2 . 它们可能会同时访问全局的对象(比如 cout ). 
这时我们希望对 func1 和 func2 的调用是同步的. 即执行其中一个的时候. 另一个要等待.

这就用到了 boost::asio::strand 类. 它可以把几个cmd包装成同步执行的. 例如前面我们向定时器注册 func1 和 func2 时. 可以改为:
boost::asio::strand the_strand;
t1.async_wait(the_strand.wrap(func1));      //包装为同步执行的
t2.async_wait(the_strand.wrap(func2)); 
这样就保证了在任何时刻. func1 和 func2 都不会同时在执行.


http://cunsh.ycool.com/post.2150877.html


timer 的一个异步等待

[plain]  view plain copy
  1. timer_.expires_from_now(boost::posix_time::seconds(1));  
  2.        timer_.async_wait(  
  3.            boost::bind(&receiver::handle_timeout, this,  
  4.              boost::asio::placeholders::error));  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值