#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; }