diff --git a/src/util/SpinMutex.h b/src/util/SpinMutex.h index cecdbb1..d880614 100644 --- a/src/util/SpinMutex.h +++ b/src/util/SpinMutex.h @@ -4,7 +4,7 @@ #pragma once #include -// A non-recursive Mutex implemented as a spin-lock. +// A non-recursive Mutex implemented as a spin-lock, implementing the Lockable requirement class SpinMutex { public: @@ -18,6 +18,8 @@ public: void lock() { while (lock_state.test_and_set(std::memory_order_acquire)); } + bool try_lock() {return !lock_state.test_and_set(std::memory_order_acquire); } + void unlock() { lock_state.clear(std::memory_order_release); } private: diff --git a/src/util/ThreadBlockingQueue.h b/src/util/ThreadBlockingQueue.h index 59fb224..26e123d 100644 --- a/src/util/ThreadBlockingQueue.h +++ b/src/util/ThreadBlockingQueue.h @@ -11,6 +11,7 @@ #include #include #include +#include "SpinMutex.h" #define MIN_ITEM_NB (1) @@ -50,7 +51,7 @@ public: /*! Destroy safe queue. */ ~ThreadBlockingQueue() { - std::lock_guard < std::mutex > lock(m_mutex); + std::lock_guard < SpinMutex > lock(m_mutex); } /** @@ -59,7 +60,7 @@ public: * \param[in] nb max of items */ void set_max_num_items(unsigned int max_num_items) { - std::lock_guard < std::mutex > lock(m_mutex); + std::lock_guard < SpinMutex > lock(m_mutex); if (max_num_items > m_max_num_items) { //Only raise the existing max size, never reduce it @@ -79,7 +80,7 @@ public: * \return true if an item was pushed into the queue, else a timeout has occured. */ bool push(const value_type& item, std::uint64_t timeout = BLOCKING_INFINITE_TIMEOUT,const char* errorMessage = nullptr) { - std::unique_lock < std::mutex > lock(m_mutex); + std::unique_lock < SpinMutex > lock(m_mutex); if (timeout == BLOCKING_INFINITE_TIMEOUT) { m_cond_not_full.wait(lock, [this]() // Lambda funct @@ -113,7 +114,7 @@ public: * \param[in] item An item. */ bool try_push(const value_type& item) { - std::lock_guard < std::mutex > lock(m_mutex); + std::lock_guard < SpinMutex > lock(m_mutex); if (m_queue.size() >= m_max_num_items) { return false; @@ -131,7 +132,7 @@ public: * \return true if get an item from the queue, false if no item is received before the timeout. */ bool pop(value_type& item, std::uint64_t timeout = BLOCKING_INFINITE_TIMEOUT, const char* errorMessage = nullptr) { - std::unique_lock < std::mutex > lock(m_mutex); + std::unique_lock < SpinMutex > lock(m_mutex); if (timeout == BLOCKING_INFINITE_TIMEOUT) { m_cond_not_empty.wait(lock, [this]() // Lambda funct @@ -166,7 +167,7 @@ public: * \return False is returned if no item is available. */ bool try_pop(value_type& item) { - std::lock_guard < std::mutex > lock(m_mutex); + std::lock_guard < SpinMutex > lock(m_mutex); if (m_queue.empty()) { return false; @@ -184,7 +185,7 @@ public: * \return Number of items in the queue. */ size_type size() const { - std::lock_guard < std::mutex > lock(m_mutex); + std::lock_guard < SpinMutex > lock(m_mutex); return m_queue.size(); } @@ -193,7 +194,7 @@ public: * \return true if queue is empty. */ bool empty() const { - std::lock_guard < std::mutex > lock(m_mutex); + std::lock_guard < SpinMutex > lock(m_mutex); return m_queue.empty(); } @@ -202,7 +203,7 @@ public: * \return true if queue is full. */ bool full() const { - std::lock_guard < std::mutex > lock(m_mutex); + std::lock_guard < SpinMutex > lock(m_mutex); return (m_queue.size() >= m_max_num_items); } @@ -210,7 +211,7 @@ public: * Remove any items in the queue. */ void flush() { - std::lock_guard < std::mutex > lock(m_mutex); + std::lock_guard < SpinMutex > lock(m_mutex); m_queue.clear(); m_cond_not_full.notify_all(); } @@ -221,8 +222,8 @@ private: std::deque m_queue; - mutable std::mutex m_mutex; - std::condition_variable m_cond_not_empty; - std::condition_variable m_cond_not_full; + mutable SpinMutex m_mutex; + std::condition_variable_any m_cond_not_empty; + std::condition_variable_any m_cond_not_full; size_t m_max_num_items = MIN_ITEM_NB; }; diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index aa4a166..6f7cfe0 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -88,7 +88,7 @@ void WaterfallCanvas::attachSpectrumCanvas(SpectrumCanvas *canvas_in) { } void WaterfallCanvas::processInputQueue() { - std::lock_guard < SpinMutex > lock(tex_update); + std::lock_guard < std::mutex > lock(tex_update); gTimer.update(); @@ -127,7 +127,7 @@ void WaterfallCanvas::processInputQueue() { } void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { - std::lock_guard < SpinMutex > lock(tex_update); + std::lock_guard < std::mutex > lock(tex_update); wxPaintDC dc(this); const wxSize ClientSize = GetClientSize(); @@ -913,7 +913,7 @@ void WaterfallCanvas::updateCenterFrequency(long long freq) { } void WaterfallCanvas::setLinesPerSecond(int lps) { - std::lock_guard < SpinMutex > lock(tex_update); + std::lock_guard < std::mutex > lock(tex_update); linesPerSecond = lps; diff --git a/src/visual/WaterfallCanvas.h b/src/visual/WaterfallCanvas.h index 52dc5db..d7ba9de 100644 --- a/src/visual/WaterfallCanvas.h +++ b/src/visual/WaterfallCanvas.h @@ -14,7 +14,6 @@ #include "SpectrumCanvas.h" #include "WaterfallPanel.h" #include "Timer.h" -#include "SpinMutex.h" class WaterfallCanvas: public InteractiveCanvas { public: @@ -94,7 +93,7 @@ private: Timer gTimer; double lpsIndex; bool preBuf; - SpinMutex tex_update; + std::mutex tex_update; int minBandwidth; std::atomic_bool fft_size_changed; // event table