Reputation: 143
I have a class called Timer
that exposes two methods called start
and stop
.
void Timer::start() {
_enabled.store(true, std::memory_order::memory_order_release);
_timer.expires_from_now(_delay);
_timer.async_wait(
std::bind(
&Timer::tick,
this,
std::placeholders::_1
));
}
void Timer::stop() {
_enabled.store(false, std::memory_order::memory_order_release);
_timer.cancel();
}
void Timer::tick(const boost::system::error_code& error) {
if (error) return;
if (!_enabled.load(std::memory_order::memory_order_acquire)) return;
try {
_task();
} catch (...) {}
if (_enabled.load(std::memory_order::memory_order_acquire)) {
_timer.expires_from_now(_delay);
_timer.async_wait(
std::bind(
&Timer::tick,
this,
std::placeholders::_1
));
}
}
Another class that uses an instance of Timer
(handler is executed on some other thread in a ThreadPool instance) calls stop
in its destructor. From the Boost Documentation, it is now possible that the handler will be invoked and these two functions will be executed concurrently and the handler may try to access freed resources.
SomeOtherClass::~SomeOtherClass() {
_timer.stop();
// somehow wait for _timer handler to execute
// delete[] some_thing;
// other destructive things
}
Is there anyway to wait for the handler to finish execution? I've been scratching my head all day, I am quite new to Boost, so perhaps I made a design flaw. Any help would be greatly appreciated, thanks.
Upvotes: 1
Views: 731
Reputation: 393487
A pattern is to have a shared_ptr to your Timer
(by using std::enable_shared_from_this
).
That way you can keep the timer alive as long as the handler hasn't been executed (by keeping a copy of the shared pointer bound to the handler).
Other solutions could be:
std::list
) where you delete them manually when they're no longer neededio_service
on your own thread, so you can join
the thread to await the work on the io_service
.Depending on your use cases/load patterns, one approach will be better than the others.
Samples:
std::list
to manage the lifetime of objects with service objects that participate in async operations (in this case a Session: How to pass a boost asio tcp socket to a thread for sending heartbeat to client or servershared_from_this
instead: Simple server using Boost.Asio throws an exceptionI picked answers that have some contrasting approaches (some not using Boost Asio) so you can see the trade-offs and what changes between approaches.
Upvotes: 1