我的意思是,假设您在asio计时器上执行async_wait并将更新绑定到引用类型T的函数。假设您在将其传递给async_wait之前最初在堆栈上创建了T。在async_wait结束时,它调用async_wait本身,反复更新计时器。在第一次定时器没有自行更新之前,或者在第一次调用函数之后T会超出范围时,堆栈分配的类型T是否保持活动状态?
答案 0 :(得分:10)
如果您要编写一个在堆栈上创建定时器的函数,然后调用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 :(得分:1)
我对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()的析构函数会在它击中析构函数时取消定时器。