#pragma once #include #include #include #include #include #include #include #include #include #include namespace hex { class TaskHolder; class TaskManager; class Task { public: Task() = default; Task(std::string unlocalizedName, u64 maxValue, bool background, std::function function); Task(const Task&) = delete; Task(Task &&other) noexcept; ~Task(); void update(u64 value = 0); void setMaxValue(u64 value); [[nodiscard]] bool isBackgroundTask() const; [[nodiscard]] bool isFinished() const; [[nodiscard]] bool hadException() const; [[nodiscard]] bool wasInterrupted() const; [[nodiscard]] bool shouldInterrupt() const; void clearException(); [[nodiscard]] std::string getExceptionMessage() const; [[nodiscard]] const std::string &getUnlocalizedName(); [[nodiscard]] u64 getValue() const; [[nodiscard]] u64 getMaxValue() const; void interrupt(); void setInterruptCallback(std::function callback); private: void finish(); void interruption(); void exception(const char *message); private: mutable std::mutex m_mutex; std::string m_unlocalizedName; std::atomic m_currValue = 0, m_maxValue = 0; std::function m_interruptCallback; std::function m_function; std::atomic m_shouldInterrupt = false; std::atomic m_background = true; std::atomic m_interrupted = false; std::atomic m_finished = false; std::atomic m_hadException = false; std::string m_exceptionMessage; struct TaskInterruptor { virtual ~TaskInterruptor() = default; }; friend class TaskHolder; friend class TaskManager; }; class TaskHolder { public: TaskHolder() = default; explicit TaskHolder(std::weak_ptr task) : m_task(std::move(task)) { } [[nodiscard]] bool isRunning() const; [[nodiscard]] bool hadException() const; [[nodiscard]] bool wasInterrupted() const; [[nodiscard]] bool shouldInterrupt() const; void interrupt(); private: std::weak_ptr m_task; }; class TaskManager { public: TaskManager() = delete; static void init(); static void exit(); constexpr static auto NoProgress = 0; static TaskHolder createTask(std::string name, u64 maxValue, std::function function); static TaskHolder createBackgroundTask(std::string name, std::function function); static void collectGarbage(); static size_t getRunningTaskCount(); static size_t getRunningBackgroundTaskCount(); static std::list> &getRunningTasks(); static void doLater(const std::function &function); static void runDeferredCalls(); static void runWhenTasksFinished(const std::function &function); private: static std::mutex s_deferredCallsMutex, s_tasksFinishedMutex; static std::list> s_tasks; static std::list> s_taskQueue; static std::list> s_deferredCalls; static std::list> s_tasksFinishedCallbacks; static std::mutex s_queueMutex; static std::condition_variable s_jobCondVar; static std::vector s_workers; static void runner(const std::stop_token &stopToken); }; }