Skip to content

Commit b14e189

Browse files
committed
Add new Spinlock class.
1 parent 743d230 commit b14e189

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

src/common/classes/Spinlock.h

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* The contents of this file are subject to the Initial
3+
* Developer's Public License Version 1.0 (the "License");
4+
* you may not use this file except in compliance with the
5+
* License. You may obtain a copy of the License at
6+
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
7+
*
8+
* Software distributed under the License is distributed AS IS,
9+
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing rights
11+
* and limitations under the License.
12+
*
13+
* The Original Code was created by Adriano dos Santos Fernandes
14+
* for the Firebird Open Source RDBMS project.
15+
*
16+
* Copyright (c) 2025 Adriano dos Santos Fernandes <adrianosf@gmail.com>
17+
* and all contributors signed below.
18+
*
19+
* All Rights Reserved.
20+
* Contributor(s): ______________________________________.
21+
*/
22+
23+
#ifndef CLASSES_SPINLOCK_H
24+
#define CLASSES_SPINLOCK_H
25+
26+
#include <atomic>
27+
#include <thread>
28+
29+
namespace Firebird {
30+
31+
32+
// Spinlock implementation that can be used in shared memory.
33+
// Based in example found in https://en.cppreference.com/w/cpp/atomic/atomic_flag.html
34+
// Compatible with std::lock_guard, std::scoped_lock and std::unique_lock.
35+
class SpinLock
36+
{
37+
std::atomic_flag atomicFlag = ATOMIC_FLAG_INIT;
38+
39+
public:
40+
void lock() noexcept
41+
{
42+
while (atomicFlag.test_and_set(std::memory_order_acquire))
43+
{
44+
#if defined(__cpp_lib_atomic_wait) && __cpp_lib_atomic_wait >= 201907L
45+
// Since C++20, locks can be acquired only after notification in the unlock,
46+
// avoiding any unnecessary spinning.
47+
// Note that even though wait guarantees it returns only after the value has
48+
// changed, the lock is acquired after the next condition check.
49+
atomicFlag.wait(true, std::memory_order_relaxed);
50+
#else
51+
std::this_thread::yield();
52+
#endif
53+
}
54+
}
55+
56+
bool try_lock() noexcept
57+
{
58+
return !atomicFlag.test_and_set(std::memory_order_acquire);
59+
}
60+
61+
void unlock() noexcept
62+
{
63+
atomicFlag.clear(std::memory_order_release);
64+
#if defined(__cpp_lib_atomic_wait) && __cpp_lib_atomic_wait >= 201907L
65+
atomicFlag.notify_one();
66+
#endif
67+
}
68+
};
69+
70+
71+
} // namespace Firebird
72+
73+
#endif // CLASSES_SPINLOCK_H

0 commit comments

Comments
 (0)