Skip to content

Commit 65b5b20

Browse files
committed
Restructure Concurrency
1 parent a46a7f8 commit 65b5b20

File tree

6 files changed

+135
-82
lines changed

6 files changed

+135
-82
lines changed

src/AudioTools/AudioLibs/Concurrency.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
* @ingroup main
55
* @brief Multicore support
66
*/
7-
#include "AudioTools/Concurrency/All.h"
7+
#include "AudioTools/Concurrency/RTOS.h"

src/AudioTools/Concurrency/LockGuard.h

Lines changed: 8 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,10 @@
11
#pragma once
22
#include "AudioConfig.h"
33
#include "AudioTools/CoreAudio/AudioLogger.h"
4-
5-
#ifdef USE_STD_CONCURRENCY
6-
# include <mutex>
7-
#endif
8-
9-
#ifdef ESP32
10-
# include "freertos/FreeRTOS.h"
11-
# include "freertos/semphr.h"
12-
#else
13-
# include "FreeRTOS.h"
14-
# include "semphr.h"
15-
#endif
4+
#include "Mutex.h"
165

176
namespace audio_tools {
187

19-
/**
20-
* @brief Empty Mutex implementation which does nothing
21-
* @ingroup concurrency
22-
* @author Phil Schatzmann
23-
* @copyright GPLv3
24-
*/
25-
class MutexBase {
26-
public:
27-
virtual void lock() {}
28-
virtual void unlock() {}
29-
};
30-
31-
#if defined(USE_STD_CONCURRENCY)
32-
33-
/**
34-
* @brief Mutex implemntation based on std::mutex
35-
* @ingroup concurrency
36-
* @author Phil Schatzmann
37-
* @copyright GPLv3
38-
*/
39-
class StdMutex : public MutexBase {
40-
public:
41-
void lock() override { std_mutex.lock(); }
42-
void unlock() override { std_mutex.unlock(); }
43-
44-
protected:
45-
std::mutex std_mutex;
46-
};
47-
48-
#endif
49-
50-
51-
/**
52-
* @brief Mutex implemntation using FreeRTOS
53-
* @ingroup concurrency
54-
* @author Phil Schatzmann
55-
* @copyright GPLv3 *
56-
*/
57-
class Mutex : public MutexBase {
58-
public:
59-
Mutex() {
60-
TRACED();
61-
xSemaphore = xSemaphoreCreateBinary();
62-
xSemaphoreGive(xSemaphore);
63-
}
64-
~Mutex() {
65-
TRACED();
66-
vSemaphoreDelete(xSemaphore);
67-
}
68-
void lock() override {
69-
TRACED();
70-
xSemaphoreTake(xSemaphore, portMAX_DELAY);
71-
}
72-
void unlock() override {
73-
TRACED();
74-
xSemaphoreGive(xSemaphore);
75-
}
76-
77-
protected:
78-
SemaphoreHandle_t xSemaphore = NULL;
79-
};
80-
818

829
/**
8310
* @brief RAII implementaion using a Mutex: Only a few microcontrollers provide
@@ -90,23 +17,25 @@ class Mutex : public MutexBase {
9017
*/
9118
class LockGuard {
9219
public:
93-
LockGuard(Mutex &mutex) {
20+
LockGuard(MutexBase &mutex) {
9421
TRACED();
9522
p_mutex = &mutex;
9623
p_mutex->lock();
9724
}
98-
LockGuard(Mutex *mutex) {
25+
LockGuard(MutexBase *mutex) {
9926
TRACED();
10027
p_mutex = mutex;
101-
p_mutex->lock();
28+
if (p_mutex != nullptr)
29+
p_mutex->lock();
10230
}
10331
~LockGuard() {
10432
TRACED();
105-
p_mutex->unlock();
33+
if (p_mutex != nullptr)
34+
p_mutex->unlock();
10635
}
10736

10837
protected:
109-
Mutex *p_mutex = nullptr;
38+
MutexBase *p_mutex = nullptr;
11039
};
11140

11241
}

src/AudioTools/Concurrency/Mutex.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#pragma once
2+
#include "AudioConfig.h"
3+
#include <atomic>
4+
5+
#ifdef USE_STD_CONCURRENCY
6+
# include <mutex>
7+
#endif
8+
9+
namespace audio_tools {
10+
11+
/**
12+
* @brief Empty Mutex implementation which does nothing
13+
* @ingroup concurrency
14+
* @author Phil Schatzmann
15+
* @copyright GPLv3
16+
*/
17+
class MutexBase {
18+
public:
19+
virtual void lock() {}
20+
virtual void unlock() {}
21+
};
22+
23+
24+
class SpinLock : public MutexBase {
25+
std::atomic<bool> lock_ = {0};
26+
27+
void lock() {
28+
for (;;) {
29+
// Optimistically assume the lock is free on the first try
30+
if (!lock_.exchange(true, std::memory_order_acquire)) {
31+
return;
32+
}
33+
// Wait for lock to be released without generating cache misses
34+
while (lock_.load(std::memory_order_relaxed)) {
35+
// Issue X86 PAUSE or ARM YIELD instruction to reduce contention between
36+
// hyper-threads
37+
//__builtin_ia32_pause();
38+
delay(1);
39+
}
40+
}
41+
}
42+
43+
bool try_lock() {
44+
// First do a relaxed load to check if lock is free in order to prevent
45+
// unnecessary cache misses if someone does while(!try_lock())
46+
return !lock_.load(std::memory_order_relaxed) &&
47+
!lock_.exchange(true, std::memory_order_acquire);
48+
}
49+
50+
void unlock() {
51+
lock_.store(false, std::memory_order_release);
52+
}
53+
};
54+
55+
56+
#if defined(USE_STD_CONCURRENCY)
57+
58+
/**
59+
* @brief Mutex implemntation based on std::mutex
60+
* @ingroup concurrency
61+
* @author Phil Schatzmann
62+
* @copyright GPLv3
63+
*/
64+
class StdMutex : public MutexBase {
65+
public:
66+
void lock() override { std_mutex.lock(); }
67+
void unlock() override { std_mutex.unlock(); }
68+
69+
protected:
70+
std::mutex std_mutex;
71+
};
72+
73+
#endif
74+
75+
76+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#pragma once
2+
#include "AudioConfig.h"
3+
#include "Mutex.h"
4+
5+
#ifdef ESP32
6+
# include "freertos/FreeRTOS.h"
7+
# include "freertos/semphr.h"
8+
#else
9+
# include "FreeRTOS.h"
10+
# include "semphr.h"
11+
#endif
12+
13+
namespace audio_tools {
14+
15+
/**
16+
* @brief Mutex implemntation using FreeRTOS
17+
* @ingroup concurrency
18+
* @author Phil Schatzmann
19+
* @copyright GPLv3 *
20+
*/
21+
class Mutex : public MutexBase {
22+
public:
23+
Mutex() {
24+
TRACED();
25+
xSemaphore = xSemaphoreCreateBinary();
26+
xSemaphoreGive(xSemaphore);
27+
}
28+
~Mutex() {
29+
TRACED();
30+
vSemaphoreDelete(xSemaphore);
31+
}
32+
void lock() override {
33+
TRACED();
34+
xSemaphoreTake(xSemaphore, portMAX_DELAY);
35+
}
36+
void unlock() override {
37+
TRACED();
38+
xSemaphoreGive(xSemaphore);
39+
}
40+
41+
protected:
42+
SemaphoreHandle_t xSemaphore = NULL;
43+
};
44+
45+
}

src/AudioTools/Concurrency/All.h renamed to src/AudioTools/Concurrency/RTOS.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
#include "AudioTools/Concurrency/BufferRTOS.h"
44
#include "AudioTools/Concurrency/SynchronizedBuffers.h"
55
#include "AudioTools/Concurrency/Task.h"
6+
#include "MutexRTOS.h"
67
#include "AudioTools/Concurrency/LockGuard.h"

src/AudioTools/Concurrency/SynchronizedBuffers.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "AudioTools/CoreAudio/Buffers.h"
66
#include "AudioTools/CoreAudio/AudioLogger.h"
77

8+
89
#ifdef ESP32
910
# include "freertos/FreeRTOS.h"
1011
# include "AudioTools/Concurrency/QueueRTOS.h"
@@ -15,6 +16,7 @@
1516
# include "stream_buffer.h"
1617
#endif
1718

19+
#include "Mutex.h"
1820
#include "LockGuard.h"
1921

2022
namespace audio_tools {
@@ -31,7 +33,7 @@ namespace audio_tools {
3133
template <typename T>
3234
class SynchronizedBuffer : public BaseBuffer<T> {
3335
public:
34-
SynchronizedBuffer(BaseBuffer<T> &buffer, Mutex &mutex, bool syncAvailable=false) {
36+
SynchronizedBuffer(BaseBuffer<T> &buffer, MutexBase &mutex, bool syncAvailable=false) {
3537
p_buffer = &buffer;
3638
p_mutex = &mutex;
3739
is_sync_available = syncAvailable;
@@ -120,7 +122,7 @@ class SynchronizedBuffer : public BaseBuffer<T> {
120122

121123
protected:
122124
BaseBuffer<T> *p_buffer = nullptr;
123-
Mutex *p_mutex = nullptr;
125+
MutexBase *p_mutex = nullptr;
124126
bool is_sync_available = false;
125127
};
126128

0 commit comments

Comments
 (0)