ion 0.12.0
Atomic concurrency support library
Loading...
Searching...
No Matches
spinLock.hpp
Go to the documentation of this file.
1/**
2 * @defgroup ion_locks Locks
3 * Provides ion::SpinLock.
4 *
5 * @ingroup ion
6 *
7 * @file
8 * @ingroup ion_locks
9 *
10 * @brief ion::SpinLock
11 *
12 * @copyright
13 * SPDX-FileCopyrightText: 2022-2024 European Southern Observatory (ESO)
14
15 * SPDX-License-Identifier: LGPL-3.0-only
16 */
17#ifndef ION_SPINLOCK_HPP
18#define ION_SPINLOCK_HPP
19#include <atomic>
20
21#include <ion/detail/macros.hpp>
22
23namespace ion {
24
25/**
26 * Busy spinning lock that satisfies
27 * [*BasicLockable*](https://en.cppreference.com/w/cpp/named_req/BasicLockable),
28 * [*Lockable*](https://en.cppreference.com/w/cpp/named_req/Lockable) and
29 * [*Mutex*](https://en.cppreference.com/w/cpp/named_req/Mutex) requirements.
30 *
31 * Implementation busy-spins without sleeping or yielding, does not detect resource
32 * deadlocks and does not throw any exceptions.
33 *
34 * @note This is not suitable for most general programs.
35 *
36 * Can be used with e.g. [`std::lock_guard`](https://en.cppreference.com/w/cpp/thread/lock_guard),
37 * [`std::scoped_lock`](https://en.cppreference.com/w/cpp/thread/scoped_lock) and
38 * [`std::unique_lock`](https://en.cppreference.com/w/cpp/thread/unique_lock).
39 *
40 * @memory_order{
41 * See [*Mutex*](https://en.cppreference.com/w/cpp/named_req/Mutex).
42 * }
43 * @thread_safe
44 * @ingroup ion_locks
45 * @headerfile <> <ion/spinLock.hpp>
46 */
47class SpinLock {
48public:
49 SpinLock() noexcept = default;
50 SpinLock(SpinLock const&) = delete;
51
52 /**
53 * Acquires the lock.
54 *
55 * @pre lock must not be held.
56 * @post lock is held.
57 */
58 inline void lock() noexcept; // NOLINT(readability-identifier-naming)
59
60 /**
61 * Attempts to acquire the lock.
62 *
63 * @pre lock must not be held.
64 *
65 * @returns true if lock was acquired.
66 * @returns false otherwise.
67 */
68 ION_FORCE_INLINE inline bool try_lock() noexcept; // NOLINT(readability-identifier-naming)
69
70 /**
71 * Releases held lock.
72 *
73 * @pre lock must be held.
74 */
75 inline void unlock() noexcept; // NOLINT(readability-identifier-naming)
76
77private:
78 static_assert(std::atomic_bool::is_always_lock_free);
79
80 /// true if locked.
81 std::atomic_bool m_lock = false;
82};
83
84void SpinLock::lock() noexcept { // NOLINT(readability-identifier-naming)
85 while (!try_lock()) {
86 ION_PAUSE();
87 }
88}
89
90bool SpinLock::try_lock() noexcept { // NOLINT(readability-identifier-naming)
91 return m_lock.load(std::memory_order_relaxed) == false &&
92 m_lock.exchange(true, std::memory_order_acquire) == false;
93}
94
95void SpinLock::unlock() noexcept { // NOLINT(readability-identifier-naming)
96 m_lock.store(false, std::memory_order_release);
97}
98
99} // namespace ion
100#endif // ION_SPINLOCK_HPP
ION_FORCE_INLINE bool try_lock() noexcept
Attempts to acquire the lock.
Definition spinLock.hpp:90
void lock() noexcept
Acquires the lock.
Definition spinLock.hpp:84
void unlock() noexcept
Releases held lock.
Definition spinLock.hpp:95