70 lines
No EOL
1.6 KiB
C++
70 lines
No EOL
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;
|
|
} |