66#include <condition_variable>
94 if (sched_getaffinity(0,
sizeof(mask), &mask) == 0)
96 const int n = CPU_COUNT(&mask);
98 return static_cast<unsigned>(n);
101 const unsigned hw = std::thread::hardware_concurrency();
102 return hw >= 1 ? hw : 1u;
124 if (
const char* env = std::getenv(
"BERTINI_NUM_THREADS"))
126 int n = std::atoi(env);
128 return static_cast<unsigned>(n);
142 std::deque<T> queue_;
144 std::condition_variable cv_;
151 std::lock_guard<std::mutex> lock(mutex_);
152 queue_.push_back(std::move(item));
160 std::unique_lock<std::mutex> lock(mutex_);
161 cv_.wait(lock, [
this]{
return !queue_.empty(); });
162 T item = std::move(queue_.front());
170 std::lock_guard<std::mutex> lock(mutex_);
173 T item = std::move(queue_.front());
196template<
typename TaskT,
typename ResultT,
typename StateFactory,
typename TrackFn>
199 using StateT = std::invoke_result_t<StateFactory>;
200 using WorkItem = std::variant<TaskT, PoolShutdownSentinel>;
204 std::vector<std::thread> threads_;
213 : n_threads_(n_threads)
215 threads_.reserve(
static_cast<size_t>(n_threads));
216 for (
int i = 0; i < n_threads; ++i)
218 threads_.emplace_back([
this, state_factory, track_fn]()
mutable
221 StateT state = state_factory();
225 WorkItem item = task_queue_.pop();
227 if (std::holds_alternative<PoolShutdownSentinel>(item))
230 TaskT
const& task = std::get<TaskT>(item);
231 ResultT result = track_fn(state, task);
232 result_queue_.push(std::move(result));
241 task_queue_.push(WorkItem{std::move(task)});
247 return result_queue_.pop();
253 return result_queue_.try_pop();
259 for (
int i = 0; i < n_threads_; ++i)
260 task_queue_.push(WorkItem{PoolShutdownSentinel{}});
261 for (
auto& t : threads_)
A simple thread-safe (mutex + condition-variable) FIFO queue.
Definition thread_pool.hpp:141
T pop()
Block until an item is available, then pop and return it.
Definition thread_pool.hpp:158
std::optional< T > try_pop()
Pop and return an item if one is ready, otherwise std::nullopt (non-blocking).
Definition thread_pool.hpp:168
void push(T item)
Push an item onto the queue and wake one waiter.
Definition thread_pool.hpp:148
WorkerThreadPool(int n_threads, StateFactory state_factory, TrackFn track_fn)
Construct the pool and start n_threads worker threads, each with its own state.
Definition thread_pool.hpp:212
void shutdown()
Signal all threads to exit and join (call only after all results are collected).
Definition thread_pool.hpp:257
ResultT collect()
Block until one result is available, then return it.
Definition thread_pool.hpp:245
void submit(TaskT task)
Submit a task to be tracked by a worker thread.
Definition thread_pool.hpp:239
std::optional< ResultT > try_collect()
Return a result if one is ready, otherwise std::nullopt (non-blocking).
Definition thread_pool.hpp:251
Definition initialize_finalize.hpp:43
unsigned AvailableCpuCount()
The number of CPUs this process may run on.
Definition thread_pool.hpp:89
unsigned EffectiveThreadCount(unsigned configured=0)
Resolve a configured thread count to the number of worker threads to actually spawn.
Definition thread_pool.hpp:122
Definition algorithm_builder.hpp:36
Definition thread_pool.hpp:180