WE Core
Loading...
Searching...
No Matches
AudioSpinMutex.h
Go to the documentation of this file.
1
/*
2
* File: AudioSpinMutex.h
3
*
4
* Created: 22/10/2021
5
*
6
* This file is part of WECore.
7
*
8
* WECore is free software: you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation, either version 3 of the License, or
11
* (at your option) any later version.
12
*
13
* WECore is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU General Public License
19
* along with WECore. If not, see <http://www.gnu.org/licenses/>.
20
*/
21
22
#pragma once
23
24
#include <array>
25
#include <thread>
26
#include <atomic>
27
28
// Some useful links about these instructions in notes/splnlock-instructions.txt
29
#if defined(__x86_64__) || defined(_M_AMD64)
30
#include <emmintrin.h>
31
#define CPU_PAUSE _mm_pause();
32
#elif defined(__aarch64__) || defined(_M_ARM64)
33
#define CPU_PAUSE __asm__ __volatile__("yield" ::: "memory");
34
#else
35
#error Unsupported architecture
36
#endif
37
38
namespace
WECore
{
39
46
class
AudioSpinMutex
{
47
public
:
48
AudioSpinMutex
() =
default
;
49
~AudioSpinMutex
() =
default
;
50
56
void
lock
() {
57
constexpr
std::array iterations = {5, 10, 3000};
58
59
for
(
int
i = 0; i < iterations[0]; ++i) {
60
if
(
tryLock
()) {
61
return
;
62
}
63
}
64
65
for
(
int
i = 0; i < iterations[1]; ++i) {
66
if
(
tryLock
()) {
67
return
;
68
}
69
70
CPU_PAUSE
71
}
72
73
while
(
true
) {
74
for
(
int
i = 0; i < iterations[2]; ++i) {
75
if
(
tryLock
()) {
76
return
;
77
}
78
79
CPU_PAUSE
80
CPU_PAUSE
81
CPU_PAUSE
82
CPU_PAUSE
83
CPU_PAUSE
84
CPU_PAUSE
85
CPU_PAUSE
86
CPU_PAUSE
87
CPU_PAUSE
88
CPU_PAUSE
89
}
90
91
// Waiting longer than we should, let's give other threads
92
// a chance to recover
93
std::this_thread::yield();
94
}
95
}
96
102
bool
tryLock
() {
103
return
!
flag
.test_and_set(std::memory_order_acquire);
104
}
105
109
void
unlock
() {
110
flag
.clear(std::memory_order_release);
111
}
112
113
private
:
114
std::atomic_flag
flag
= ATOMIC_FLAG_INIT;
115
};
116
117
class
AudioSpinLockBase
{
118
public
:
119
AudioSpinLockBase
(
AudioSpinMutex
& mutex) :
_mutex
(mutex),
_isLocked
(false) { }
120
121
~AudioSpinLockBase
() {
122
if
(
_isLocked
) {
123
_mutex
.
unlock
();
124
}
125
}
126
127
void
unlock
() {
128
if
(
_isLocked
) {
129
_mutex
.
unlock
();
130
_isLocked
=
false
;
131
}
132
}
133
134
bool
isLocked
() {
return
_isLocked
; }
135
136
protected
:
137
AudioSpinMutex
&
_mutex
;
138
139
// Keeps track of whether this lock is still holding the mutex. Must always check this
140
// internally before calling unlock on the mutex, otherwise we might unlock it, then the lock
141
// is taken by someone else, then we unlock it again.
142
bool
_isLocked
;
143
};
144
148
class
AudioSpinLock
:
public
AudioSpinLockBase
{
149
public
:
150
explicit
AudioSpinLock
(
AudioSpinMutex
& mutex) :
AudioSpinLockBase
(mutex) {
151
_mutex
.
lock
();
152
_isLocked
=
true
;
153
}
154
};
155
159
class
AudioSpinTryLock
:
public
AudioSpinLockBase
{
160
public
:
161
explicit
AudioSpinTryLock
(
AudioSpinMutex
& mutex) :
AudioSpinLockBase
(mutex) {
162
_isLocked
=
_mutex
.
tryLock
();
163
}
164
};
165
}
WECore::AudioSpinLockBase
Definition
AudioSpinMutex.h:117
WECore::AudioSpinLockBase::unlock
void unlock()
Definition
AudioSpinMutex.h:127
WECore::AudioSpinLockBase::isLocked
bool isLocked()
Definition
AudioSpinMutex.h:134
WECore::AudioSpinLockBase::_mutex
AudioSpinMutex & _mutex
Definition
AudioSpinMutex.h:137
WECore::AudioSpinLockBase::~AudioSpinLockBase
~AudioSpinLockBase()
Definition
AudioSpinMutex.h:121
WECore::AudioSpinLockBase::AudioSpinLockBase
AudioSpinLockBase(AudioSpinMutex &mutex)
Definition
AudioSpinMutex.h:119
WECore::AudioSpinLockBase::_isLocked
bool _isLocked
Definition
AudioSpinMutex.h:142
WECore::AudioSpinLock
Definition
AudioSpinMutex.h:148
WECore::AudioSpinLock::AudioSpinLock
AudioSpinLock(AudioSpinMutex &mutex)
Definition
AudioSpinMutex.h:150
WECore::AudioSpinMutex
Definition
AudioSpinMutex.h:46
WECore::AudioSpinMutex::lock
void lock()
Definition
AudioSpinMutex.h:56
WECore::AudioSpinMutex::AudioSpinMutex
AudioSpinMutex()=default
WECore::AudioSpinMutex::unlock
void unlock()
Definition
AudioSpinMutex.h:109
WECore::AudioSpinMutex::tryLock
bool tryLock()
Definition
AudioSpinMutex.h:102
WECore::AudioSpinMutex::flag
std::atomic_flag flag
Definition
AudioSpinMutex.h:114
WECore::AudioSpinMutex::~AudioSpinMutex
~AudioSpinMutex()=default
WECore::AudioSpinTryLock
Definition
AudioSpinMutex.h:159
WECore::AudioSpinTryLock::AudioSpinTryLock
AudioSpinTryLock(AudioSpinMutex &mutex)
Definition
AudioSpinMutex.h:161
WECore
Definition
CarveDSPUnit.h:55
WECore
General
AudioSpinMutex.h
Generated by
1.12.0