#pragma once #include #include #include #include #include #include class CancelationPointReached : public std::runtime_error { public: explicit CancelationPointReached() : std::runtime_error("CancelationPointReached") {} }; class Threading { public: Threading() = default; ~Threading(); protected: void preInit() const; void createThread(); void runThread(); inline bool isRun() const { return (m_run != 0); } inline void setRun(bool run) { m_run = (run ? 1 : 0); } inline void setWorkAvailable(bool workAvailable) { m_workAvailable = (workAvailable ? 1 : 0); } inline bool isWorkAvailable() const { return (m_workAvailable != 0); } inline void setWorking(bool working) { m_isWorking = (working ? 1 : 0); } inline bool isWorking() const { return (m_isWorking != 0); } const QString &threadName() const; inline const char *posixThreadName() const; virtual void work() = 0; virtual QString functionTopicName() const = 0; virtual int partitionId() const = 0; virtual QString partitionType() const = 0; virtual void cleanupThread() = 0; virtual void threadDone() = 0; inline void cancellationPoint() const noexcept(false) { if (!isRun()) { throw CancelationPointReached(); } } std::mutex m_conditionMutex; private: inline bool isCleanupNeeded() const { return (m_cleanupNeeded != 0); } inline void setCleanupNeeded(bool cleanupNeeded) { m_cleanupNeeded = (cleanupNeeded ? 1 : 0); } void run(const QString &threadName); std::unique_ptr m_threadLifetime; QAtomicInt m_run { 0 }; QAtomicInt m_cleanupNeeded { 1 }; std::thread m_thread; std::condition_variable m_condition; QAtomicInt m_workAvailable { 0 }; QAtomicInt m_isWorking { 0 }; mutable QString m_threadName; mutable std::string m_posixThreadName; QAtomicInt m_alreadyThreaded; mutable int m_partitionId { -1 }; mutable QString m_partitionType; bool m_used { false }; bool m_createThreadCalledBefore { false }; };