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 plaincopy
  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));  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章