Когда таймер Asio выходит из области видимости? - PullRequest
7 голосов
/ 13 марта 2010

Я имею в виду, скажем, вы выполняете async_wait на таймере asio и связываете обновление с функцией, которая получает ссылку на тип T. Допустим, вы изначально создали T в стеке, прежде чем передать его async_wait. В конце этого async_wait он вызывает async_wait, обновляя таймер снова и снова. Будет ли этот стек, выделенный для типа T, оставаться в живых до тех пор, пока таймер в первый раз не обновится, или после первого вызова функции T выйдет из области видимости?

Ответы [ 2 ]

10 голосов
/ 14 марта 2010

Если вы напишите функцию, в которой вы создадите таймер в стеке, а затем вызовите async_wait, таймер будет уничтожен в конце вызова функции, и обратный вызов немедленно будет вызван с соответствующим параметром ошибки.

Вы не можете передать объект таймера обратному вызову, используя boost :: bind, так как объект не подлежит копированию.

Тем не менее, вы можете управлять связывателем в куче, передавая общий указатель на каждый вызов async_wait. Это может выглядеть так:

void MyClass::addTimer(int milliseconds) // Initial timer creation call
{
  boost::shared_ptr<boost::asio::deadline_timer> t
    (new boost::asio::deadline_timer
     (m_io_service, 
      boost::posix_time::milliseconds(milliseconds)));
  // Timer object is being passed to the handler
  t->async_wait(boost::bind(&MyClass::handle_timer,
                            this,
                            t,
                            milliseconds));

}

void MyClass::handle_timer(boost::shared_ptr<boost::asio::deadline_timer> & t,
                               int milliseconds)
{
  // Push the expiry back using the same tick
  t->expires_at(t->expires_at() + boost::posix_time::milliseconds(milliseconds));
  t->async_wait(boost::bind(&MyClass::handle_timer,
                            this,
                            t,
                            milliseconds));
  onTimer(); // Do something useful
}
1 голос
/ 13 марта 2010

У меня нет опыта работы с таймерами Asio. Но если вы делаете

void somefunc( void )
{
  boost::asio::io_service io;

  boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
}

Тогда таймер выходит из области видимости при выходе из функции. Так что с этим кодом не нужно ждать. Если вы добавите t.wait () к этому коду, он подождет 5 секунд и выйдет из функции, а таймер выйдет из области видимости.

void somefunc( void )
{
  boost::asio::io_service io;

  boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
  t.async_wait(somecallback);

  io.run();
}

Во втором примере таймер выходит из области видимости при выходе из функции.

Если вы хотите обойти таймер, я думаю, вы должны написать так.

void somefunc( void )
{
  boost::asio::io_service io;

  while( something )
  {
    boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
    t.async_wait(somecallback);

    io.run();
  }
}

Это будет держать таймер в стеке на один оборот в цикле, а затем он будет воссоздан. Если вы поместите таймер за пределы цикла, он никогда не выйдет за рамки видимости. Но тогда вы должны сбросить его каким-либо образом, включив цикл. Но я не вижу такой функции.

РЕДАКТИРОВАТЬ : В примере с async_wait () таймер будет уничтожен вне области, непосредственно без завершения, если у вас нет io.run (), чтобы заставить его ждать. И я бы предположил, что дескриптор deadline_timer () выполнит отмену таймера при попадании в деструктор.

...