Boost logo

Boost Users :

Subject: Re: [Boost-users] boost::asio::deadline_timer destruction
From: Igor R (boost.lists_at_[hidden])
Date: 2013-04-19 13:38:54


>> > I've noticed that WaitHandler can be called after
>> > boost::asio::deadline_timer destruction. It may cause using of uninitialized
>> > data. Are there any other solutions of graceful destruction of
>> > boost::asio::deadline_timer to be sure that after this destruction
>> > WaitHandler will never be called?
>>
>>
>> Yes, the solution is to use shared_from_this idiom.
>
<...>
> But it requires of changing construction model. What if I want allocate objects at stack?
> May be there are some technique which doesn't require from user to use shared_ptr technique?

The bottom line is that the completion handler should outlive its
async. operation. So you have 2 ways:
1) To create an "automatic linkage" between the operation and the
handler, i.e. to cause the handler to be alive as long as the
operation is in progress. Eg., you can pass the handler functor by
value or by smart ptr.
2) To control the handler lifetime manually. No techniques here, just
ad-hoc solution that matches your specific scenario.
Of course the 1st approach is much more robust and preferable in most cases.
(Note that it was not necessary to create the completion handler as a
binder based on an object containing the i/o object that initiates the
async. operation -- it was your deliberate choice... And by the way,
it seems that you attempt to cancel the timer from a non-io-service
thread, don't you? If yes, it's not thread-safe.)

> For example why boost::asio::deadline_timer::~deadline_timer doesn't wait completion of WaitHandler?

It can't because it doesn't dispatch completion handlers. It's
io_service who is in charge of this.
But even if it could, it would be rather a problem than a solution.
Consider the following trivial program:

#include <boost/asio.hpp>
#include <boost/date_time/time_duration.hpp>
#include <boost/bind.hpp>

using namespace boost;
using namespace boost::asio;
using namespace boost::posix_time;

void f(const system::error_code&, const deadline_timer *t)
{
  delete t; // to wait or not to wait?
}

int main()
{
  io_service io;
  deadline_timer *t = new deadline_timer(io);
  t->expires_from_now(seconds(10));
  t->async_wait(boost::bind(&f, _1, t));
  io.run();
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net