reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

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