mirror of
https://github.com/LizardByte/Sunshine.git
synced 2024-11-17 08:09:50 +00:00
122 lines
2.3 KiB
C++
122 lines
2.3 KiB
C++
#ifndef KITTY_THREAD_POOL_H
|
|
#define KITTY_THREAD_POOL_H
|
|
|
|
#include <thread>
|
|
#include "task_pool.h"
|
|
|
|
namespace util {
|
|
/*
|
|
* Allow threads to execute unhindered
|
|
* while keeping full controll over the threads.
|
|
*/
|
|
class ThreadPool : public TaskPool {
|
|
public:
|
|
typedef TaskPool::__task __task;
|
|
|
|
private:
|
|
std::vector<std::thread> _thread;
|
|
|
|
std::condition_variable _cv;
|
|
std::mutex _lock;
|
|
|
|
bool _continue;
|
|
public:
|
|
ThreadPool() : _continue { false } {}
|
|
|
|
explicit ThreadPool(int threads) : _thread(threads), _continue { true } {
|
|
for (auto &t : _thread) {
|
|
t = std::thread(&ThreadPool::_main, this);
|
|
}
|
|
}
|
|
|
|
~ThreadPool() noexcept {
|
|
if (!_continue) return;
|
|
|
|
stop();
|
|
join();
|
|
}
|
|
|
|
template<class Function, class... Args>
|
|
auto push(Function && newTask, Args &&... args) {
|
|
std::lock_guard lg(_lock);
|
|
auto future = TaskPool::push(std::forward<Function>(newTask), std::forward<Args>(args)...);
|
|
|
|
_cv.notify_one();
|
|
return future;
|
|
}
|
|
|
|
void pushDelayed(std::pair<__time_point, __task> &&task) {
|
|
std::lock_guard lg(_lock);
|
|
|
|
TaskPool::pushDelayed(std::move(task));
|
|
}
|
|
|
|
template<class Function, class X, class Y, class... Args>
|
|
auto pushDelayed(Function &&newTask, std::chrono::duration<X, Y> duration, Args &&... args) {
|
|
std::lock_guard lg(_lock);
|
|
auto future = TaskPool::pushDelayed(std::forward<Function>(newTask), duration, std::forward<Args>(args)...);
|
|
|
|
// Update all timers for wait_until
|
|
_cv.notify_all();
|
|
return future;
|
|
}
|
|
|
|
void start(int threads) {
|
|
_continue = true;
|
|
|
|
_thread.resize(threads);
|
|
|
|
for(auto &t : _thread) {
|
|
t = std::thread(&ThreadPool::_main, this);
|
|
}
|
|
}
|
|
|
|
void stop() {
|
|
std::lock_guard lg(_lock);
|
|
|
|
_continue = false;
|
|
_cv.notify_all();
|
|
}
|
|
|
|
void join() {
|
|
for (auto & t : _thread) {
|
|
t.join();
|
|
}
|
|
}
|
|
|
|
public:
|
|
|
|
void _main() {
|
|
while (_continue) {
|
|
if(auto task = this->pop()) {
|
|
(*task)->run();
|
|
}
|
|
else {
|
|
std::unique_lock uniq_lock(_lock);
|
|
|
|
if(ready()) {
|
|
continue;
|
|
}
|
|
|
|
if(!_continue) {
|
|
break;
|
|
}
|
|
|
|
if(auto tp = next()) {
|
|
_cv.wait_until(uniq_lock, *tp);
|
|
}
|
|
else {
|
|
_cv.wait(uniq_lock);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Execute remaining tasks
|
|
while(auto task = this->pop()) {
|
|
(*task)->run();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
#endif
|