2015-03-14 5 views
0

у меня есть повышающий deadline_timer, который работает периодически (как в примере http://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/tutorial/tuttimer3/src.html):атомарной отменить ASIO asynchronious таймер из другого потока

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

void print(const boost::system::error_code& /*e*/, 
    boost::asio::deadline_timer* t) 
{ 
    t->expires_at(t->expires_at() + boost::posix_time::seconds(1)); 
    t->async_wait(boost::bind(print, 
      boost::asio::placeholders::error, t, count)); 
} 

int main() 
{ 
    boost::asio::io_service io; 

    boost::asio::deadline_timer t(io, boost::posix_time::seconds(1)); 
    t.async_wait(boost::bind(print, 
     boost::asio::placeholders::error, &t)); 

    io.run(); 

    return 0; 
} 

Теперь мне нужно, чтобы отменить его из другого потока. Но что, если вызов отмены отображается только во время выполнения функции печати, но до истечения срока действия expires_at? Затем таймер будет продолжать работать.

Один из способов борьбы с ним, чтобы запустить что-то вроде

while (timer.cancel() == 0) { 
} 

в этой отдельной функции потока.

Но может быть, кто-нибудь знает более элегантный способ, которым эта проблема может быть решена?

ответ

2

На самом деле оба подхода не совсем безопасны, только потому, что deadline_timer является not thread-safe.

ИМО, самый простой и безопасный способ заключается в post отмены:

//... 
timer.get_io_service().post([&]{timer.cancel();}) 
//... 

Примечание: в реальном коде один должен гарантировать, что timer переживет функтор (лямбда).

UPDATE: как уже упоминалось, это решение может не сработать - поскольку обработчик отмены может появиться в очереди io_service перед print, когда таймер больше не ждет.

+0

Обратите внимание, что это имеет потенциал для состояния гонки (отправленный 'cancel()' может возникать в то время, когда 'async_await' не находится в ожидании). См. https://stackoverflow.com/questions/43168199 – sehe

+0

@sehe ahh, right, good catch. –