Hi all,
I started playing with ASIO timers and after scanning through the relevant
docs, I set up a small case. Please find below the code snippet.
The IntervalEvent class is supposed to fire the event provided on the
construction at a frequency equal to the durationInterval.
Somehow the code below fails to compile on VC7.1.
I am getting several warnings and the error:
c:\program files\boost\boost_1_38\boost\mem_fn.hpp(343) : error C4716:
'boost::_mfi::dm
m_timer.async_wait(boost::bind(&IntervalEvent::handler, this));
should be: m_timer.async_wait(boost::bind(&IntervalEvent::handler, this, _1)); or: m_timer.async_wait(boost::bind(&IntervalEvent::handler, this, boost::asio::placeholders::error));
void handler(boost::system::error_code& error)
should be: void handler(cosnt boost::system::error_code& error)
Further to that, I am wondering, in principle should I cancel the deadline_timer on the destructor of the IntervalEvent class? Does the io_service class know when any of the deadline_timers that is being registered goes out of scope?
On destruction, the timer cancels itself anyway. By the way, you access the timers both from main() and from another thread - which is illegal, since the asio objects are not thread-safe (except for io_service).
Thank you very much Igor.
I acknowledge my ignorence regarding the thread safety issues involved, so I
would like dig a little bit deeper here, if you do not mind. If there is a
point in the docs that I should be looking and that I have not my apologies.
I would appreciate it if you could point me there.
Most of the examples that I have come across for timers have as a
precondition that the io_service::run function has been invoked yet;
reseting the timer happens withing the timer handler in general.
I am wondering what are the issues involved when calling
deadline_timer::async_wait, deadline_timer::cancel for a timer that is
associated with an io_service object when io_service::run has already
started in a different thread? Or in other words following the point "* the
io_service may be being run in a background thread that is launched prior to
the application's asynchronous operations*" in
http://www.boost.org/doc/libs/1_38_0/doc/html/boost_asio/reference/io_servic...,
how do I launch asynch operations using an io_service that has already being
run?
This is relevant to what I really want to do which is:
1.Start io_service::run in one background thread
2.Start async timers on demand from the main thread that should be executed
on the io_service::run thread. These timers will be associated with an event
that will trigger a thread safe handler on a registerd observer(in this case
the Counter class).
3. Modify/cancel from the main thread timers that have outstanding async
operations in the io_service::run thread.
In the particular example below, the member function onIncrement of the
class Counter is not thread safe, but since the io_service::run is running
on a one thread, only one handler will be invoked on the thread that runs
io_service::run, so implicitly there is a serialization of access, correct?
My question is what is the best practice, in order to achieve 2 and 3 above?
Suprisingly, after building my toy case with your help, the effect is what I
expected, but I admit that your comment made me realize that I still need to
dig further in order to understand all the issues involved.
I would be grateful for any comment or suggestion.
Thanks a lot.
Kimon
On Sat, Apr 25, 2009 at 8:38 PM, Igor R
m_timer.async_wait(boost::bind(&IntervalEvent::handler, this));
should be: m_timer.async_wait(boost::bind(&IntervalEvent::handler, this, _1)); or: m_timer.async_wait(boost::bind(&IntervalEvent::handler, this, boost::asio::placeholders::error));
void handler(boost::system::error_code& error)
should be: void handler(cosnt boost::system::error_code& error)
Further to that, I am wondering, in principle should I cancel the deadline_timer on the destructor of the IntervalEvent class? Does the io_service class know when any of the deadline_timers that is being registered goes out of scope?
On destruction, the timer cancels itself anyway.
By the way, you access the timers both from main() and from another thread - which is illegal, since the asio objects are not thread-safe (except for io_service). _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Hi all,
I changed the implementation(please find it attached) so any change in the
timers is forwarded through a io_service::post call to a protected handler.
It works and it looks to me that there are no real thread safety issues. Can
anybody confirm my understanding?
Also I am wondering should the initiazation of an async_wait be forwarded
through io_service::post on the first time that a deadline_timer is set for
an io_service that is running on a different thread?
Here
http://www.boost.org/doc/libs/1_38_0/doc/html/boost_asio/reference/basic_dea...,
is stated that
" *Invocation of the handler will be performed in a manner equivalent to
using boost::asio::io_service::post().* ".
Any comments or suggestions are more than welcome.
Thank you
Kimon
Please find attached the new implementation. My understanding is that
io_service::post gives the strongest guarantee that the handler will be
invoked in the
On Sun, Apr 26, 2009 at 12:22 AM, Kimon Simons
Thank you very much Igor.
I acknowledge my ignorence regarding the thread safety issues involved, so I would like dig a little bit deeper here, if you do not mind. If there is a point in the docs that I should be looking and that I have not my apologies. I would appreciate it if you could point me there.
Most of the examples that I have come across for timers have as a precondition that the io_service::run function has been invoked yet; reseting the timer happens withing the timer handler in general. I am wondering what are the issues involved when calling deadline_timer::async_wait, deadline_timer::cancel for a timer that is associated with an io_service object when io_service::run has already started in a different thread? Or in other words following the point "*the io_service may be being run in a background thread that is launched prior to the application's asynchronous operations*" in http://www.boost.org/doc/libs/1_38_0/doc/html/boost_asio/reference/io_servic..., how do I launch asynch operations using an io_service that has already being run?
This is relevant to what I really want to do which is:
1.Start io_service::run in one background thread 2.Start async timers on demand from the main thread that should be executed on the io_service::run thread. These timers will be associated with an event that will trigger a thread safe handler on a registerd observer(in this case the Counter class). 3. Modify/cancel from the main thread timers that have outstanding async operations in the io_service::run thread.
In the particular example below, the member function onIncrement of the class Counter is not thread safe, but since the io_service::run is running on a one thread, only one handler will be invoked on the thread that runs io_service::run, so implicitly there is a serialization of access, correct?
My question is what is the best practice, in order to achieve 2 and 3 above? Suprisingly, after building my toy case with your help, the effect is what I expected, but I admit that your comment made me realize that I still need to dig further in order to understand all the issues involved.
I would be grateful for any comment or suggestion.
Thanks a lot.
Kimon
On Sat, Apr 25, 2009 at 8:38 PM, Igor R
wrote: m_timer.async_wait(boost::bind(&IntervalEvent::handler, this));
should be: m_timer.async_wait(boost::bind(&IntervalEvent::handler, this, _1)); or: m_timer.async_wait(boost::bind(&IntervalEvent::handler, this, boost::asio::placeholders::error));
void handler(boost::system::error_code& error)
should be: void handler(cosnt boost::system::error_code& error)
Further to that, I am wondering, in principle should I cancel the deadline_timer on the destructor of the IntervalEvent class? Does the io_service class know when any of the deadline_timers that is being registered goes out of scope?
On destruction, the timer cancels itself anyway.
By the way, you access the timers both from main() and from another thread - which is illegal, since the asio objects are not thread-safe (except for io_service). _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
I am wondering what are the issues involved when calling deadline_timer::async_wait, deadline_timer::cancel for a timer that is associated with an io_service object when io_service::run has already started in a different thread? Or in other words following the point " the io_service may be being run in a background thread that is launched prior to the application's asynchronous operations" in http://www.boost.org/doc/libs/1_38_0/doc/html/boost_asio/reference/io_servic..., how do I launch asynch operations using an io_service that has already being run?
Since the io_service itself is thread-safe, there's no problem to attach asio objects to it from another thread. I.e., you can create deadline_timer's from within the main thread, just like you do in your code. However, cancelling the timers might cause race-condition, because io_service's thread might try to access the timer at the very same moment. To avoid this you can apply the pattern, which is widely used in asio examples: private: void IntervalEvent::syncCancel() { m_timer.cancel(); } public: void IntervalEvent::cancel() { // m_timer.cancel(); instead of cancelling here, just re-post this action to io_service thread(s) // invoke another member function, in case of a complex action m_timer.get_io_service().post(bind(&IntervalEvent::syncCancel, this)); // or, in case of simple action, just construct it on-the-fly: m_timer.get_io_service().post(bind(&deadline_timer::cancel, boost::ref(m_timer))); } Any access to a running timer/socket can be made this way. As for initial async_wait(), I can't see any potential race-conditions, so I guess it's ok to do this from the main thread.
In the particular example below, the member function onIncrement of the class Counter is not thread safe, but since the io_service::run is running on a one thread, only one handler will be invoked on the thread that runs io_service::run, so implicitly there is a serialization of access, correct?
Counter::onIncrement is invoked from one thread, that's true. But writing there to std::cout is not thread-safe anyway, because std::cout is not exclusively owned by Counter.
participants (2)
-
Igor R
-
Kimon Simons