diff --git a/include/util/threadpool.h b/include/util/threadpool.h index 126343a..39b25f5 100644 --- a/include/util/threadpool.h +++ b/include/util/threadpool.h @@ -9,15 +9,46 @@ #include #include +#include +#include namespace blt { + class runnable { + public: + virtual void run() = 0; + virtual ~runnable() = default; + }; + + /** + * If your runnable functions are small consider using another data structure, + * as thread_pool will be slow if many small tasks are needed to be ran. + * thread_pool is designed for running large long run tasks + */ class thread_pool { private: - + volatile bool halted; + int MAX_THREADS; + std::queue runQueue {}; + std::vector threads {}; + std::mutex queueMutex {}; public: + explicit thread_pool(int maxThreads); + + /** + * Attempts to start the thread_pool. + */ + void start(); + + void run(std::function& func); + + void run(runnable* func); + + void stop(); + + ~thread_pool(); }; - + } #endif //FINALPROJECT_THREADPOOL_H diff --git a/src/util/threadpool.cpp b/src/util/threadpool.cpp index aade380..3a7e55a 100644 --- a/src/util/threadpool.cpp +++ b/src/util/threadpool.cpp @@ -3,4 +3,76 @@ * Licensed under GNU General Public License V3.0 * See LICENSE file for license detail */ -#include \ No newline at end of file +#include + +class runnable_function : public blt::runnable { + private: + std::function& func; + public: + explicit runnable_function(std::function& func): func(func) {} + + void run() final { + func(); + } +}; + +blt::thread_pool::thread_pool(int maxThreads): MAX_THREADS(maxThreads) { + halted = false; +} + +blt::thread_pool::~thread_pool() { + stop(); +} + +void blt::thread_pool::start() { + for (int i = 0; i < MAX_THREADS; i++) { + threads.push_back( + new std::thread( + [this]() -> void { + while (!halted){ + // acquire a resource from the runnable queue + std::unique_lock lock(queueMutex); + runnable* run = runQueue.front(); + runQueue.pop(); + lock.unlock(); + + // attempt to run the function + run->run(); + + delete(run); + } + } + )); + } +} + +void blt::thread_pool::stop() { + if (halted) + return; + + halted = true; + + for (std::thread* thread : threads) + thread->join(); + + for (std::thread* thread : threads) + delete thread; + + std::scoped_lock lock(queueMutex); + while (!runQueue.empty()){ + delete runQueue.front(); + runQueue.pop(); + } +} + +void blt::thread_pool::run(std::function& func) { + std::scoped_lock lock(queueMutex); + runQueue.push(new runnable_function(func)); +} + +void blt::thread_pool::run(blt::runnable* func) { + std::scoped_lock lock(queueMutex); + runQueue.push(func) +} + +