diff --git a/src/slic3r/GUI/Jobs/BoostThreadWorker.hpp b/src/slic3r/GUI/Jobs/BoostThreadWorker.hpp index a8d38cf771..3d11097e2a 100644 --- a/src/slic3r/GUI/Jobs/BoostThreadWorker.hpp +++ b/src/slic3r/GUI/Jobs/BoostThreadWorker.hpp @@ -67,6 +67,11 @@ class BoostThreadWorker : public Worker, private Job::Ctl void deliver(BoostThreadWorker &runner); }; + // The m_running state flag needs special attention. Previously, it was set simply in the run() + // method whenever a new job was taken from the input queue and unset after the finalize message + // was pushed into the output queue. This was not correct. It must not be possible to consume + // the finalize message before the flag gets unset, these two operations must be done atomically + // So the underlying queues are here extended to support handling of this m_running flag. template class RawQueue: public std::deque { std::atomic *m_running_ptr; @@ -79,6 +84,7 @@ class BoostThreadWorker : public Worker, private Job::Ctl void set_stopped() { m_running_ptr->store(false); } }; + // The running flag is set if a job is popped from the queue template class RawJobQueue: public RawQueue { public: @@ -90,6 +96,7 @@ class BoostThreadWorker : public Worker, private Job::Ctl } }; + // The running flag is unset when the finalize message is pushed into the queue template class RawMsgQueue: public RawQueue { public: diff --git a/src/slic3r/GUI/Jobs/ThreadSafeQueue.hpp b/src/slic3r/GUI/Jobs/ThreadSafeQueue.hpp index 05c14f9cdc..e0d423d4b9 100644 --- a/src/slic3r/GUI/Jobs/ThreadSafeQueue.hpp +++ b/src/slic3r/GUI/Jobs/ThreadSafeQueue.hpp @@ -21,10 +21,6 @@ struct BlockingWait unsigned timeout_ms = 0; }; -template -using NonSpecialMembersOnly = std::enable_if_t< - (sizeof...(Args) >= 1) && !(... || std::is_convertible_v)>; - // A thread safe queue for one producer and one consumer. template class Container = std::deque, @@ -36,15 +32,16 @@ class ThreadSafeQueueSPSC std::condition_variable m_cond_var; public: - template> + + // Forward arguments to the underlying queue + template ThreadSafeQueueSPSC(Qargs &&...qargs) : m_queue{Container{std::forward(qargs)...}} {} - ThreadSafeQueueSPSC() = default; - ThreadSafeQueueSPSC(const ThreadSafeQueueSPSC&) = default; - ThreadSafeQueueSPSC(ThreadSafeQueueSPSC&&) = default; - ThreadSafeQueueSPSC& operator=(const ThreadSafeQueueSPSC&) = default; - ThreadSafeQueueSPSC& operator=(ThreadSafeQueueSPSC &&) = default; + ThreadSafeQueueSPSC(const ThreadSafeQueueSPSC&) = delete; + ThreadSafeQueueSPSC(ThreadSafeQueueSPSC&&) = delete; + ThreadSafeQueueSPSC& operator=(const ThreadSafeQueueSPSC&) = delete; + ThreadSafeQueueSPSC& operator=(ThreadSafeQueueSPSC &&) = delete; // Consume one element, block if the queue is empty. template