mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2025-09-02 13:17:48 -04:00
More Spin locks experiments
This commit is contained in:
parent
fd30710d14
commit
1d2e35cbac
@ -4,7 +4,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
// A non-recursive Mutex implemented as a spin-lock.
|
// A non-recursive Mutex implemented as a spin-lock, implementing the Lockable requirement
|
||||||
class SpinMutex {
|
class SpinMutex {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -18,6 +18,8 @@ public:
|
|||||||
|
|
||||||
void lock() { while (lock_state.test_and_set(std::memory_order_acquire)); }
|
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); }
|
void unlock() { lock_state.clear(std::memory_order_release); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "SpinMutex.h"
|
||||||
|
|
||||||
#define MIN_ITEM_NB (1)
|
#define MIN_ITEM_NB (1)
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ public:
|
|||||||
|
|
||||||
/*! Destroy safe queue. */
|
/*! Destroy safe queue. */
|
||||||
~ThreadBlockingQueue() {
|
~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
|
* \param[in] nb max of items
|
||||||
*/
|
*/
|
||||||
void set_max_num_items(unsigned int max_num_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) {
|
if (max_num_items > m_max_num_items) {
|
||||||
//Only raise the existing max size, never reduce it
|
//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.
|
* \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) {
|
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) {
|
if (timeout == BLOCKING_INFINITE_TIMEOUT) {
|
||||||
m_cond_not_full.wait(lock, [this]() // Lambda funct
|
m_cond_not_full.wait(lock, [this]() // Lambda funct
|
||||||
@ -113,7 +114,7 @@ public:
|
|||||||
* \param[in] item An item.
|
* \param[in] item An item.
|
||||||
*/
|
*/
|
||||||
bool try_push(const value_type& 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) {
|
if (m_queue.size() >= m_max_num_items) {
|
||||||
return false;
|
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.
|
* \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) {
|
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) {
|
if (timeout == BLOCKING_INFINITE_TIMEOUT) {
|
||||||
m_cond_not_empty.wait(lock, [this]() // Lambda funct
|
m_cond_not_empty.wait(lock, [this]() // Lambda funct
|
||||||
@ -166,7 +167,7 @@ public:
|
|||||||
* \return False is returned if no item is available.
|
* \return False is returned if no item is available.
|
||||||
*/
|
*/
|
||||||
bool try_pop(value_type& item) {
|
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()) {
|
if (m_queue.empty()) {
|
||||||
return false;
|
return false;
|
||||||
@ -184,7 +185,7 @@ public:
|
|||||||
* \return Number of items in the queue.
|
* \return Number of items in the queue.
|
||||||
*/
|
*/
|
||||||
size_type size() const {
|
size_type size() const {
|
||||||
std::lock_guard < std::mutex > lock(m_mutex);
|
std::lock_guard < SpinMutex > lock(m_mutex);
|
||||||
return m_queue.size();
|
return m_queue.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +194,7 @@ public:
|
|||||||
* \return true if queue is empty.
|
* \return true if queue is empty.
|
||||||
*/
|
*/
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
std::lock_guard < std::mutex > lock(m_mutex);
|
std::lock_guard < SpinMutex > lock(m_mutex);
|
||||||
return m_queue.empty();
|
return m_queue.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,7 +203,7 @@ public:
|
|||||||
* \return true if queue is full.
|
* \return true if queue is full.
|
||||||
*/
|
*/
|
||||||
bool full() const {
|
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);
|
return (m_queue.size() >= m_max_num_items);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +211,7 @@ public:
|
|||||||
* Remove any items in the queue.
|
* Remove any items in the queue.
|
||||||
*/
|
*/
|
||||||
void flush() {
|
void flush() {
|
||||||
std::lock_guard < std::mutex > lock(m_mutex);
|
std::lock_guard < SpinMutex > lock(m_mutex);
|
||||||
m_queue.clear();
|
m_queue.clear();
|
||||||
m_cond_not_full.notify_all();
|
m_cond_not_full.notify_all();
|
||||||
}
|
}
|
||||||
@ -221,8 +222,8 @@ private:
|
|||||||
|
|
||||||
std::deque<T> m_queue;
|
std::deque<T> m_queue;
|
||||||
|
|
||||||
mutable std::mutex m_mutex;
|
mutable SpinMutex m_mutex;
|
||||||
std::condition_variable m_cond_not_empty;
|
std::condition_variable_any m_cond_not_empty;
|
||||||
std::condition_variable m_cond_not_full;
|
std::condition_variable_any m_cond_not_full;
|
||||||
size_t m_max_num_items = MIN_ITEM_NB;
|
size_t m_max_num_items = MIN_ITEM_NB;
|
||||||
};
|
};
|
||||||
|
@ -88,7 +88,7 @@ void WaterfallCanvas::attachSpectrumCanvas(SpectrumCanvas *canvas_in) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WaterfallCanvas::processInputQueue() {
|
void WaterfallCanvas::processInputQueue() {
|
||||||
std::lock_guard < SpinMutex > lock(tex_update);
|
std::lock_guard < std::mutex > lock(tex_update);
|
||||||
|
|
||||||
gTimer.update();
|
gTimer.update();
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ void WaterfallCanvas::processInputQueue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
||||||
std::lock_guard < SpinMutex > lock(tex_update);
|
std::lock_guard < std::mutex > lock(tex_update);
|
||||||
wxPaintDC dc(this);
|
wxPaintDC dc(this);
|
||||||
|
|
||||||
const wxSize ClientSize = GetClientSize();
|
const wxSize ClientSize = GetClientSize();
|
||||||
@ -913,7 +913,7 @@ void WaterfallCanvas::updateCenterFrequency(long long freq) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WaterfallCanvas::setLinesPerSecond(int lps) {
|
void WaterfallCanvas::setLinesPerSecond(int lps) {
|
||||||
std::lock_guard < SpinMutex > lock(tex_update);
|
std::lock_guard < std::mutex > lock(tex_update);
|
||||||
|
|
||||||
linesPerSecond = lps;
|
linesPerSecond = lps;
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include "SpectrumCanvas.h"
|
#include "SpectrumCanvas.h"
|
||||||
#include "WaterfallPanel.h"
|
#include "WaterfallPanel.h"
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
#include "SpinMutex.h"
|
|
||||||
|
|
||||||
class WaterfallCanvas: public InteractiveCanvas {
|
class WaterfallCanvas: public InteractiveCanvas {
|
||||||
public:
|
public:
|
||||||
@ -94,7 +93,7 @@ private:
|
|||||||
Timer gTimer;
|
Timer gTimer;
|
||||||
double lpsIndex;
|
double lpsIndex;
|
||||||
bool preBuf;
|
bool preBuf;
|
||||||
SpinMutex tex_update;
|
std::mutex tex_update;
|
||||||
int minBandwidth;
|
int minBandwidth;
|
||||||
std::atomic_bool fft_size_changed;
|
std::atomic_bool fft_size_changed;
|
||||||
// event table
|
// event table
|
||||||
|
Loading…
x
Reference in New Issue
Block a user