DSPark 1.8.0
Header-only C++20 DSP for real-time and offline audio
Loading...
Searching...
No Matches
SpinLock.h
1// DSPark -- Professional Audio DSP Framework
2// Copyright (c) 2026 Cristian Moresi -- MIT License
3
4#pragma once
5
45#include <atomic>
46
47#if (defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))) \
48 || defined(__x86_64__) || defined(__i386__) || defined(__SSE2__)
49 // x86 / x86-64 (any compiler): PAUSE spin hint.
50 #include <immintrin.h>
51 #define DSPARK_SPIN_PAUSE() _mm_pause()
52#elif defined(_MSC_VER) && defined(_M_ARM64)
53 // MSVC on ARM64: _mm_pause() does not exist here; use the YIELD intrinsic.
54 #include <intrin.h>
55 #define DSPARK_SPIN_PAUSE() __yield()
56#elif defined(__aarch64__) || defined(__arm__) || defined(__ARM_NEON)
57 // GCC/Clang on ARM: YIELD instruction.
58 #define DSPARK_SPIN_PAUSE() __asm__ __volatile__("yield")
59#else
60 // WebAssembly / unknown: safe no-op.
61 #define DSPARK_SPIN_PAUSE() ((void)0)
62#endif
63
64namespace dspark {
65
77{
78public:
80 SpinLock() noexcept = default;
81
82 SpinLock(const SpinLock&) = delete;
83 SpinLock& operator=(const SpinLock&) = delete;
84
95 void lock() noexcept
96 {
97 for (;;)
98 {
99 // Attempt to grab the lock
100 if (!flag_.test_and_set(std::memory_order_acquire)) {
101 return;
102 }
103
104 // Spin on a relaxed read to prevent cache line bouncing
105 while (flag_.test(std::memory_order_relaxed)) {
106 DSPARK_SPIN_PAUSE(); // Hint CPU to yield resources during spin
107 }
108 }
109 }
110
115 [[nodiscard]] bool tryLock() noexcept
116 {
117 return !flag_.test_and_set(std::memory_order_acquire);
118 }
119
126 [[nodiscard]] bool try_lock() noexcept { return tryLock(); }
127
131 void unlock() noexcept
132 {
133 flag_.clear(std::memory_order_release);
134 }
135
136 // ========================================================================
137
143 {
144 public:
149 explicit ScopedLock(SpinLock& spinLock) noexcept : lock_(spinLock) { lock_.lock(); }
150
152 ~ScopedLock() noexcept { lock_.unlock(); }
153
154 ScopedLock(const ScopedLock&) = delete;
155 ScopedLock& operator=(const ScopedLock&) = delete;
156
157 private:
158 SpinLock& lock_;
159 };
160
169 {
170 public:
175 explicit ScopedTryLock(SpinLock& spinLock) noexcept
176 : lock_(spinLock), acquired_(spinLock.tryLock()) {}
177
179 ~ScopedTryLock() noexcept { if (acquired_) lock_.unlock(); }
180
185 [[nodiscard]] bool isLocked() const noexcept { return acquired_; }
186
187 ScopedTryLock(const ScopedTryLock&) = delete;
189
190 private:
191 SpinLock& lock_;
192 bool acquired_;
193 };
194
195private:
196 // C++20 default initialization correctly sets the atomic_flag to the clear state.
197 // ATOMIC_FLAG_INIT is deprecated in C++20 and removed in C++26.
198 std::atomic_flag flag_{};
199};
200
201} // namespace dspark
RAII wrapper that acquires the lock on construction and releases on destruction.
Definition SpinLock.h:143
~ScopedLock() noexcept
Destructs the guard and releases the lock.
Definition SpinLock.h:152
ScopedLock & operator=(const ScopedLock &)=delete
ScopedLock(SpinLock &spinLock) noexcept
Constructs the guard and blocks until the lock is acquired.
Definition SpinLock.h:149
ScopedLock(const ScopedLock &)=delete
RAII wrapper that tries to acquire the lock without blocking.
Definition SpinLock.h:169
ScopedTryLock & operator=(const ScopedTryLock &)=delete
~ScopedTryLock() noexcept
Destructs the guard and releases the lock ONLY if it was successfully acquired.
Definition SpinLock.h:179
ScopedTryLock(const ScopedTryLock &)=delete
bool isLocked() const noexcept
Queries whether the lock acquisition was successful.
Definition SpinLock.h:185
ScopedTryLock(SpinLock &spinLock) noexcept
Constructs the guard and attempts a single lock acquisition.
Definition SpinLock.h:175
A minimal, real-time safe spin lock with a TTAS wait loop.
Definition SpinLock.h:77
bool tryLock() noexcept
Attempts to acquire the lock without waiting.
Definition SpinLock.h:115
void unlock() noexcept
Releases the lock, restoring it to the clear state.
Definition SpinLock.h:131
SpinLock() noexcept=default
Constructs an unlocked SpinLock.
bool try_lock() noexcept
Standard-library spelling of tryLock().
Definition SpinLock.h:126
void lock() noexcept
Acquires the lock, spinning until successful.
Definition SpinLock.h:95
Main namespace for the DSPark framework.