|
Boost Users : |
Subject: Re: [Boost-users] boost::asio::deadline_timer destruction
From: Daniel (zin_corp_at_[hidden])
Date: 2013-04-19 14:01:12
Igor,
Why deadline_timer doesn't wait WaitHandler completion?
I don't understand why did you delete object from wait handler...
I meant a little bit different thing like this:
class graceful_deadline_timer : public boost::asio::deadline_timer
{
typedef boost::asio::deadline_timer super;
boost::function1<void, const boost::system::error_code&> handler;
boost::condition_variable_any wait_handler_done;
boost::recursive_mutex wait_handler_lock;
bool expired;
void handler_wrapper(const boost::system::error_code &ec)
{
boost::lock_guard<boost::recursive_mutex> lock(wait_handler_lock);
handler(ec);
expired = true;
wait_handler_done.notify_all();
}
public:
explicit graceful_deadline_timer(boost::asio::io_service& io_service) : super(io_service), expired(true)
{
}
~graceful_deadline_timer()
{
boost::unique_lock<boost::recursive_mutex> lock(wait_handler_lock);
if(!expired)
{
cancel();
while(!expired)
{
wait_handler_done.wait(lock);
}
}
}
template <typename WaitHandler>
void async_wait(WaitHandler _handler)
{
boost::lock_guard<boost::recursive_mutex> lock(wait_handler_lock);
handler = _handler;
expired = false;
super::async_wait(boost::bind(&graceful_deadline_timer::handler_wrapper, this, boost::asio::placeholders::error));
}
};
Thank you,
Daniel
> >> > 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 mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>
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