Skip to content

Commit

Permalink
Thread pool can now receive tasks to do
Browse files Browse the repository at this point in the history
  • Loading branch information
jyrkive committed Sep 29, 2018
1 parent 9f1e456 commit 6716227
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
2 changes: 0 additions & 2 deletions src/thread_pool.cpp
Expand Up @@ -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()
Expand All @@ -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;
}
Expand Down
50 changes: 49 additions & 1 deletion src/thread_pool.hpp
Expand Up @@ -13,6 +13,7 @@

#pragma once

#include <atomic>
#include <condition_variable>
#include <functional>
#include <future>
Expand All @@ -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_;
Expand All @@ -40,7 +54,41 @@ class thread_pool
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);
}
}

0 comments on commit 6716227

Please sign in to comment.