I'm writing a server using boost::asio. I have multiple threads each owning it's own io_service
object. I'm using io_service::work
object to keep io_service
running when there is no completion handlers to execute. In certain moment I'm calling stop
method of io_service
objects to finish threads which called io_serice::run
. But in some cases when I'm calling stop
I have posted in io_service
object competion handlers which are not finished. Calling stop
prevents posted competion handlers from executing, but this is unacceptable for me because I need all pending work to be finished before stopping the thread. How to wait for all pending completion handlers first to be executed before calling stop
method of io_service
?
Just reset the work
.
Any io_service::run()
will return when all pending work has been completed.
The common pattern is to use optional<work>
so you can clear it. If it is a frequent thing, you could reduce some mental overhead by wrapping it in a RAII-enabled class:
Live On Coliru
#include <boost/asio.hpp>
#include <boost/optional.hpp>
struct work {
using io_service = boost::asio::io_service;
work(io_service& svc) : _work(io_service::work(svc))
{ }
void release() {
_work.reset();
}
void enlist(io_service& svc) {
_work.emplace(io_service::work(svc));
}
private:
boost::optional<io_service::work> _work;
};
#include <thread>
#include <iostream>
using namespace std::chrono_literals;
int main() {
boost::asio::io_service svc;
work lock(svc);
std::thread background([&] { svc.run(); });
std::this_thread::sleep_for(1s);
std::cout << "releasing work";
lock.release();
background.join();
}
Which finishes the background thread after 1 second.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With