首页 > 代码库 > BOOST ASIO 学习专贴

BOOST ASIO 学习专贴

1.同步使用Timer


本便使用了boost::asio::deadline_timer,这个timer有两种状态:过期和不过期。wait函数调用一个过期的timer直接返回。

int _tmain(int argc, _TCHAR* argv[]){    boost::asio::io_service io;    boost::asio::deadline_timer t(io,boost::posix_time::seconds(5));    t.wait();    std::cout<<"wait finished!"<<std::endl;    return 0;}

2.异步使用Timer

下在演示了使用deadline_timer的asyn_wati函数实现异步等待。但要注意的一点是异步等待必须要调用io.run才可以。而且必须在io.run函数执行之前调用asyn_wait,否则io.run会立即返回,因为他没有可以做的事。这说明io.run必须至少有一个等待的,否则它会直接返回。asio函数保证回调函数执行和io.run所在的线程一样!

//异步Timervoid print(const boost::system::error_code & ){    std::cout<<"Wait Finished"<<std::endl;}int _tmain(int argc, _TCHAR* argv[]){    boost::asio::io_service io;    boost::asio::deadline_timer t(io,boost::posix_time::seconds(5));    t.async_wait(&print);    io.run();    return 0;}

3.为回调函数绑定参数

这个例子一个是说明异步Timer的可持续性问题,也就是在回调中设置Time的超时时间。另一个说明回调函数参数的绑定 。但是实际发现我官的代码没有发生那个重复回调的效果。原因是我只是调用了expire_at而没有调用再次等待函数async_wait。这让我更加明白expires_at这个函数相当于下次触发的时间。而async_wait提交一个等待申请。

async_wait提交一次,回调函数执行一次,而expire_at设定下次回调函数调用的时间。

#include <boost/bind.hpp>void Print(const boost::system::error_code & ,           boost::asio::deadline_timer * t,int * count){    if(*count < 5)    {        std::cout<<*count<<std::endl;        ++(*count);        t->expires_at(t->expires_at() + boost::posix_time::seconds(1));        t->async_wait(boost::bind(Print,boost::asio::placeholders::error,t,count));    }}int _tmain(int argc, _TCHAR* argv[]){    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();    return 0;}

4.类成员做为timer的回调函数

这个例子主要演示了,如何绑定一个类成员函数作为一个回调

class Print{public:    Print(boost::asio::io_service & io)        :timer_(io,boost::posix_time::seconds(1)),count_(0)    {        timer_.async_wait(boost::bind(&Print::print,this));    }    ~Print()    {        std::cout<<"finnal count is "<<count_<<std::endl;    }    void print()    {        if(count_ < 5)        {            std::cout<<count_<<std::endl;            ++count_;            timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));            timer_.async_wait(boost::bind(&Print::print,this));        }    }protected:    boost::asio::deadline_timer timer_;    int count_;};int _tmain(int argc, _TCHAR* argv[]){    boost::asio::io_service io;    Print p(io);    io.run();    return 0;}

4.在多线程程序中的同步回调

先前的例子通过io_service.run和同步回调在同一个线程内,正如你所知的那样,asio保证回调函数只能被在io_service.run()所在的线程调用 。因此,只有在一个线程内调用io_service::run保证回调函数不会并发执行。这样在服务器程序中有两个局限性:

1.当回调函数执行时间比较长时响应太慢
2.没有起到多处理器的优势

如果你注意到这个局限性,一个可供选择的方案是创建一个线程池去调用io_service.run()函数,这样实现的回调的并发,我们需要去同步一个共享变量。

下面的例子使用到了An boost::asio::strand ,他保证这些回调函数通过strans派遣,它可以允许一个回调函数在另一个回调函数执行之前完成。

#include <boost/thread/thread.hpp>class printer{public:    printer(boost::asio::io_service & io)        :strand_(io),        timer1_(io,boost::posix_time::seconds(1)),        timer2_(io,boost::posix_time::seconds(1)),        count_(0)    {        timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1,this)));        timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2,this)));    }    void print1()    {        if(count_ < 10)        {            std::cout<<"Timer 1:"<<count_<<std::endl;            ++count_;            timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1));            timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1,this)));        }    }    void print2()    {        if(count_ < 10)        {            std::cout<<"Timer 2:"<<count_<<std::endl;            ++count_;            timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1));            timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2,this)));        }    }private:    boost::asio::io_service::strand strand_;    boost::asio::deadline_timer timer1_;    boost::asio::deadline_timer timer2_;    int count_;};int _tmain(int argc, _TCHAR* argv[]){    boost::asio::io_service io;    printer p(io);    boost::thread t(boost::bind(&boost::asio::io_service::run,&io));    io.run();    t.join();    return 0;}

下面有时间研究一下 boost::asio::strand的用法

BOOST ASIO 学习专贴