Thread pool can now receive tasks to do
This commit is contained in:
parent
9f1e4564df
commit
6716227279
2 changed files with 49 additions and 3 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue