thread.hpp (2576B)
1 /* ReaPack: Package manager for REAPER 2 * Copyright (C) 2015-2025 Christian Fillion 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef REAPACK_THREAD_HPP 19 #define REAPACK_THREAD_HPP 20 21 #include "errors.hpp" 22 #include "event.hpp" 23 24 #include <array> 25 #include <condition_variable> 26 #include <functional> 27 #include <queue> 28 #include <thread> 29 #include <unordered_set> 30 31 struct ThreadSummary { 32 const char *step; 33 std::string item; 34 }; 35 36 class ThreadTask { 37 public: 38 enum State { 39 Idle, 40 Queued, 41 Running, 42 Success, 43 Failure, 44 Aborted, 45 }; 46 47 ThreadTask(); 48 virtual ~ThreadTask(); 49 50 virtual bool concurrent() const = 0; 51 52 void exec(); // runs in the current thread 53 const ThreadSummary &summary() const { return m_summary; } 54 State state() const { return m_state; } 55 void setError(const ErrorInfo &err) { m_error = err; } 56 const ErrorInfo &error() { return m_error; } 57 58 bool aborted() const { return m_abort; } 59 void abort() { m_abort = true; } 60 61 AsyncEvent<void()> onStartAsync; 62 AsyncEvent<void()> onFinishAsync; 63 64 protected: 65 virtual bool run() = 0; 66 67 void setSummary(const ThreadSummary &s) { m_summary = s; } 68 69 private: 70 ThreadSummary m_summary; 71 State m_state; 72 ErrorInfo m_error; 73 std::atomic_bool m_abort; 74 }; 75 76 class WorkerThread { 77 public: 78 WorkerThread(); 79 ~WorkerThread(); 80 81 void push(ThreadTask *); 82 void clear(); 83 84 private: 85 void run(); 86 ThreadTask *nextTask(); 87 88 bool m_stop; 89 std::mutex m_mutex; 90 std::condition_variable m_wake; 91 std::queue<ThreadTask *> m_queue; 92 93 std::thread m_thread; 94 }; 95 96 class ThreadPool { 97 public: 98 ThreadPool() {} 99 ThreadPool(const ThreadPool &) = delete; 100 ~ThreadPool(); 101 102 void push(ThreadTask *); 103 void abort(); 104 105 bool idle() const { return m_running.empty(); } 106 107 Event<void(ThreadTask *)> onPush; 108 Event<void()> onAbort; 109 Event<void()> onDone; 110 111 private: 112 std::array<std::unique_ptr<WorkerThread>, 6> m_pool; 113 std::unordered_set<ThreadTask *> m_running; 114 }; 115 116 #endif