38 #include <condition_variable> 41 #include <unordered_set> 55 template <
typename Closure>
61 std::optional<Closure> task;
99 template <
typename... ArgsT>
119 bool _exiting {
false};
122 void _spawn(
unsigned);
126 template <
typename Closure>
132 template <
typename Closure>
138 template <
typename Closure>
144 template <
typename Closure>
146 return _threads.size();
150 template <
typename Closure>
161 for(
auto w : _idlers){
163 w->task = std::nullopt;
169 for(
auto& t : _threads){
178 template <
typename Closure>
179 void ProactiveThreadpool<Closure>::_spawn(
unsigned N) {
183 for(
size_t i=0; i<N; ++i){
185 _threads.emplace_back([
this] () ->
void {
196 _idlers.push_back(&w);
206 w.task = std::nullopt;
224 template <
typename Closure>
225 template <
typename... ArgsT>
229 if(num_workers() == 0){
230 Closure{std::forward<ArgsT>(args)...}();
234 std::scoped_lock lock(_mutex);
236 _tasks.emplace_back(std::forward<ArgsT>(args)...);
239 Worker* w = _idlers.back();
242 w->task.emplace(std::forward<ArgsT>(args)...);
250 template <
typename Closure>
254 if(num_workers() == 0){
262 std::scoped_lock lock(_mutex);
264 std::move(tasks.begin(), tasks.end(), std::back_inserter(_tasks));
268 while(consumed != tasks.size() && !_idlers.empty()) {
269 Worker* w = _idlers.back();
272 w->task.emplace(std::move(tasks[consumed++]));
276 if(consumed == tasks.size())
return ;
277 _tasks.reserve(_tasks.size() + tasks.size() - consumed);
278 std::move(tasks.begin()+consumed, tasks.end(), std::back_inserter(_tasks));
size_t num_workers() const
queries the number of worker threads
Definition: proactive_threadpool.hpp:145
~ProactiveThreadpool()
destructs the executor
Definition: proactive_threadpool.hpp:133
ProactiveThreadpool(unsigned N)
constructs the executor with a given number of worker threads
Definition: proactive_threadpool.hpp:127
Executor that implements a centralized task queue with a proactive execution strategy.
Definition: proactive_threadpool.hpp:56
Definition: taskflow.hpp:6
void emplace(ArgsT &&... args)
constructs the closure in place in the executor
Definition: proactive_threadpool.hpp:226
void batch(std::vector< Closure > &&closures)
moves a batch of closures to the executor
Definition: proactive_threadpool.hpp:251
bool is_owner() const
queries if the caller is the owner of the executor
Definition: proactive_threadpool.hpp:139