I believe I've ran into an edge case with thread_pool. I'm trying to create a thread pool which doesn't spawn worker threads, instead all the workers attach() to it:
#include <boost/asio/thread_pool.hpp>
#include <cstddef>
#include <thread>
#include <vector>
struct my_thread_pool : public boost::asio::thread_pool
{
explicit my_thread_pool(size_t thread_count) :
boost::asio::thread_pool(0) // don't spawn threads on your own
{
// instead use these std::threads
for (size_t x = 0; x < thread_count; ++x)
{
threads_.emplace_back(
[this]()
{
// ... some thread init code, e.g. change thread priority ...
boost::asio::thread_pool::attach();
});
}
}
void join()
{
boost::asio::thread_pool::join();
for (auto& thread : threads_)
thread.join();
threads_.clear();
}
~my_thread_pool()
{
stop();
join();
}
private:
std::vector<std::thread> threads_;
};
However, this code will deadlock
int main()
{
my_thread_pool pool(1);
pool.join();
}
The reason is that the boost::asio::thread_pool::join() call is a no-op in case there are 0 internal threads, so attached threads never leave the attach(). This contradicts the documentation for attach():
Blocks the calling thread until the pool is stopped or joined and has no outstanding work.
The fix seems simple enough.
EDIT: I got my code working by calling boost::asio::thread_pool::wait() instead of boost::asio::thread_pool::join(); this thing does what I wanted it to - It's not explicitly stated in the documentation for attach(), but it will also unblock it, unconditionally.
I believe I've ran into an edge case with
thread_pool
. I'm trying to create a thread pool which doesn't spawn worker threads, instead all the workersattach()
to it:However, this code will deadlock
The reason is that the
boost::asio::thread_pool::join()
call is a no-op in case there are 0 internal threads, so attached threads never leave theattach()
. This contradicts the documentation forattach()
:The fix seems simple enough.
EDIT: I got my code working by calling
boost::asio::thread_pool::wait()
instead ofboost::asio::thread_pool::join()
; this thing does what I wanted it to - It's not explicitly stated in the documentation forattach()
, but it will also unblock it, unconditionally.