asio学习之二:多线程同步回调和访问资源问题

时间:2022-09-08 23:17:36

asio提供了一个对象boost::asio::strand,它可以保证:对于通过它来分派执行的众操作中,只有一个操作执行完成之后才允许进入下一个操作。

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>


class printer/*定义一个class,包含两个回调函数print1和print2*/
{
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)
{

/*当开始同步操作时,每一个回调句柄都使用boost::asio::strand对象进行“包装”。strand::wrap() 函数返回一个新的通过boost::asio::strand对象自动分派的内部句柄。 通过同一boost::asio::strand对象对句柄进行“ 包装”,我们可以保证操作不会并发执行。*/
timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));
timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));
}


~printer()
{
std::cout << "Final count is " << count_ << "\n";
}

/*在一个多线程程序中,当访问同一共享资源时,异步操作必须是同步的。在本例中,print1 和print2)函数使用的共享资源std::cout 和count_数据成员。*/
void print1()
{
if (count_ < 10)
{
std::cout << "Timer 1: " << count_ << "\n";
++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_ << "\n";
++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::strand strand_;
boost::asio::deadline_timer timer1_;
boost::asio::deadline_timer timer2_;
int count_;
};

/*main函数中, io_service::run() 现在被两个线程调用:主线程和一个附加线程。这一切依赖于boost::thread对象来完成。*/
int main()
{
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;
}