Is it thread safe to post new handlers from within a handler?
I.e. Can threads that called the io_service::run()
post new Handlers to the same io_service?
Thanks
Is it thread safe to post new handlers from within a handler?
I.e. Can threads that called the io_service::run()
post new Handlers to the same io_service?
Thanks
It is safe to post handlers from within a handler for a single instance of an io_service
according to the documentation.
Thread Safety
Distinct objects: Safe.
Shared objects: Safe, with the exception that calling reset() while there are unfinished run(), run_one(), poll() or poll_one() calls results in undefined behaviour.
Note by me, who edited this post heavily: The original code had a few subtile bugs, so that it seemed to disproof thread-safety of ASIO. I have marked the corrections necessary to get the correct counter of 3000000 after execution. Look at the edit history to see the code changes made. The most important update is to change service.stop()
, which keeps some of the posted work undone, to guard.reset()
, which allows the io_service
to exit, once all work has been completed.
I choose to edit instead of post a different answer, as most of the code is still from the original author. As the later was only active many, many years ago and comments about his bugs had been made long time ago, it wouldn't have made sense to wait longer.
#include <boost/asio/io_service.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/thread.hpp>
#include <boost/thread/detail/thread_group.hpp>
#include <memory>
#include <iostream>
void postInc(boost::asio::io_service *service, std::atomic_int *counter) {
for(int i = 0; i < 100000; i++) service->post([counter] { (*counter)++; });
}
int main(int argc, char **argv)
{
std::atomic_int counter(0);
{
boost::asio::io_service service;
// boost::asio::io_service::work working(service);
auto guard = make_work_guard(service);
boost::thread_group workers;
for(size_t i = 0; i < 10;++i) workers.create_thread(boost::bind(&boost::asio::io_service::run, &service));
boost::thread_group producers;
for (int it = 0; it < 30; it++)
{
producers.add_thread(new boost::thread(boost::bind(postInc,&service,&counter)));
}
producers.join_all();
std::cout << "producers ended" << std::endl;
// service.stop();
guard.reset();
workers.join_all();
}
std::cout << counter.load() << std::endl;
return 0;
}
© 2022 - 2024 — McMap. All rights reserved.
workers
finished to work. – Migrant