Thread pool can now receive tasks to do

This commit is contained in:
Jyrki Vesterinen 2018-09-29 11:51:28 +03:00
parent 9f1e4564df
commit 6716227279
2 changed files with 49 additions and 3 deletions

View file

@ -49,7 +49,6 @@ void thread_pool::init()
num_finished_threads_ = 0u;
ready_for_work_ = false;
work_ = nullptr;
done_ = false;
}
void thread_pool::thread_proc()
@ -75,7 +74,6 @@ void thread_pool::thread_proc()
lock.lock();
++num_finished_threads_;
if(num_finished_threads_ == NUM_THREADS) {
done_ = true;
done_promise_.set_value();
work_ = nullptr;
}

View file

@ -13,6 +13,7 @@
#pragma once
#include <atomic>
#include <condition_variable>
#include <functional>
#include <future>
@ -22,14 +23,27 @@
class thread_pool
{
public:
thread_pool();
~thread_pool();
/** Runs the given workload.
@param work Container that contains objects to modify.
Can be a std::vector, std::array or std::deque.
@param func Function to call for every element in the container.
The function is assumed to edit the object in-place.
@return Future that becomes available when the task has finished. */
template<typename W, typename F>
std::future<void> run(W& work, F func);
private:
const unsigned int NUM_THREADS = 16u;
void thread_proc();
template<typename W, typename F>
void worker(W& work, F func);
void init();
std::vector<std::thread> threads_;
@ -40,7 +54,41 @@ private:
bool ready_for_work_;
std::condition_variable ready_for_work_cond_;
std::condition_variable work_cond_;
bool done_;
std::promise<void> done_promise_;
bool exiting_;
std::atomic<unsigned int> counter_;
};
template<typename W, typename F>
std::future<void> thread_pool::run(W& work, F func)
{
std::unique_lock<std::mutex> lock(mutex_);
// There must not be existing ongoing work.
assert(!work_);
while(!ready_for_work_) {
ready_for_work_cond_.wait(lock);
}
work_ = std::bind(&thread_pool::worker<W,F>, this, std::ref(work), func);
counter_ = 0u;
done_promise_ = std::promise<void>();
work_cond_.notify_all();
return done_promise_.get_future();
}
template<typename W, typename F>
void thread_pool::worker(W& work, F func)
{
// Note that fetch_add() returns the previous value.
// Thus, this returns zero for the first worker like it should.
std::atomic<unsigned int> index = counter_.fetch_add(1u,
std::memory_order::memory_order_relaxed);
while(index < work.size()) {
func(work[index]);
index = counter_.fetch_add(1u, std::memory_order::memory_order_relaxed);
}
}