vxorg/threadpool.cpp

70 lines
1.6 KiB
C++

#include "threadpool.hpp"
void ThreadPool::ThreadEntry(ThreadPool* pPool, std::size_t myIndex) {
auto& pool = *pPool;
// set a cutesy name
#ifdef __linux__
pthread_setname_np(pthread_self(), "PoolWorker");
#endif
// The thread loop
while(true) {
{
// wait for at least a single task, or shutdown notification (one of the two)
std::unique_lock lk(pool.taskQueues[myIndex].lock);
pool.queueCv.wait(lk, [&]() {
if(pool.threadsShouldShutdown)
return true;
return !pool.taskQueues[myIndex].queue.empty();
});
}
// Exit if the pool is to shutdown
if(pool.threadsShouldShutdown && pPool->QueueEmpty(myIndex))
break;
// pop and run tasks until we run out of tasks to run
{
std::unique_lock lk(pool.taskQueues[myIndex].lock);
// TODO: Work-steal from other threads.
while(!pool.taskQueues[myIndex].queue.empty()) {
auto& cb = pool.taskQueues[myIndex].queue.back();
cb();
pool.taskQueues[myIndex].queue.pop_back();
}
}
}
}
void ThreadPool::launch(std::size_t nrThreads) {
threadsShouldShutdown = false;
this->nrThreads = nrThreads;
threads.resize(this->nrThreads);
taskQueues = new TaskQueue[this->nrThreads];
for(std::size_t i = 0; i < this->nrThreads; ++i)
threads.emplace_back(std::thread(&ThreadEntry, this, i));
}
// Shutdown the thread pool
void ThreadPool::shutdown() {
if(!threadsShouldShutdown)
threadsShouldShutdown = true;
queueCv.notify_all();
// join all the threads (if possible) to make sure they all exit
for(auto& thread : threads)
if(thread.joinable())
thread.join();
nrThreads = 0;
delete[] taskQueues;
taskQueues = nullptr;
}