I have the following MyThread class that is run as a thread. This class starts a heartbeat timer (boost deadline_timer) after 30 seconds and runs every 30 seconds unless canceled. If I comment all the lines that have anything to do with boost ASIO out, my thread exits and joins properly.
However, with the ASIO code uncommented, and once I tell my thread to stop (using future and promise in Stoppable base), then my program will crash with the following:
terminate called without an active exception
Which as I understand means that I haven't joined or detached the threads within MyThread, specifically ASIO. I feel like the deadline_timer thread hasn't exited as it should by calling cancel, and even if I call io.stop, same results.
class MyThread : Stoppable {
private:
boost::asio::io_service io;
std::shared_ptr<boost::asio::deadline_timer> timer;
// ...
}
void MyThread::operator()() {
timer = std::make_shared<boost::asio::deadline_timer>(io,
boost::posix_time::seconds(30));
timer->async_wait(boost::bind(&MyThread::beat, this,
boost::asio::placeholders::error));
std::unique_ptr<std::thread> io_thread(
std::make_unique<std::thread>([&] { io.run(); }));
while (stop_requested() == false) {
// ...
// before stop() on the thread is called in main process,
// close_resources() is called.
}
}
void MyThread::beat(const boost::system::error_code &ec) {
if (ec == boost::asio::error::operation_aborted) {
// already cancelled
return;
}
timer->expires_at(hb_timer->expires_at() + boost::posix_time::seconds(30);
timer->async_wait(boost::bind(&MasterMode::beat, this,
boost::asio::placeholders::error));
send_beat();
}
void MyThread::close_resources() {
timer->get_io_service().post([&] {
int cancelled = timer->cancel();
std::cout << " # cancelled = " << cancelled << std::endl;
});
io.stop();
}
In my main process, I start MyThread class, then stop it and join as follows. This works when I don't include the ASIO code above.
{
my_class = std::make_shared<MyThread>();
my_thread = std::make_shared<std::thread>([&] { (*my_class)(); });
// ...
my_class->stop();
my_thread->join();
}
Aucun commentaire:
Enregistrer un commentaire