GCC Code Coverage Report


Directory: src/gate/
File: src/gate/atomics.hpp
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 15 15 100.0%
Functions: 6 6 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 /** @file
30 * @brief Atomic integer and pointer operations
31 * @ingroup gatecore_cpp
32 */
33
34 #ifndef GATE_ATOMICS_HPP_INCLUDED
35 #define GATE_ATOMICS_HPP_INCLUDED
36
37 #include "gate/gate_core_api.hpp"
38 #include "gate/atomics.h"
39 #include "gate/gatetypes.hpp"
40 #include "gate/results.hpp"
41 #include "gate/exceptions.hpp"
42
43 namespace gate
44 {
45
46 class GATE_CORE_CPP_API AtomicFlag : private NonCopyable ///< Atomic boolean flag
47 {
48 public:
49 AtomicFlag(bool init = false) noexcept;
50 ~AtomicFlag() noexcept;
51
52 void clear() noexcept; ///< clears atomic flag (set to false)
53 bool_t set() noexcept; ///< set atomic flag (set to true) and returns previous state
54
55 private:
56 gate_atomic_flag_t impl;
57 };
58
59 class GATE_CORE_CPP_API AtomicInt ///< Atomic 32-bit integer
60 {
61 public:
62 AtomicInt(int32_t init = 0) noexcept; ///< Initialize atomic integer
63 AtomicInt(AtomicInt const& src) noexcept;
64 AtomicInt& operator=(AtomicInt const& src) noexcept;
65 ~AtomicInt() noexcept;
66
67 gate_atomic_int_t* c_impl();
68
69 int32_t get() const noexcept; ///< Returns value of atomic integer
70 int32_t set(int32_t newvalue) noexcept; ///< Updates atomic integer to a new value and returns it previous value
71 int32_t changeIf(int32_t comparand, int32_t newvalue) noexcept; ///< Compares atomic integer with \p comparand and set its to \p newvalue if they match, returns previous value
72 bool_t updateIf(int32_t fromvalue, int32_t tovalue) noexcept; ///< Returns true if update from \p fromvalue to \p tovalue was successful
73
74 int32_t operator++() noexcept; ///< Increments atomic integer and returns its current value
75 int32_t operator++(int) noexcept; ///< Increments atomic integer and returns its previous value
76 int32_t operator--() noexcept; ///< Decrements atomic integer and returns its current value
77 int32_t operator--(int) noexcept; //< Decrements atomic integer and returns its previous value
78
79 int32_t operator+=(int32_t value) noexcept; ///< Adds number to atomic integer and returns its updated value
80 int32_t operator-=(int32_t value) noexcept; ///< Substracts number to atomic integer and returns its updated value
81
82 private:
83 gate_atomic_int_t impl;
84 };
85
86 class GATE_CORE_CPP_API AtomicInt64 ///< Atomic 64-bit integer
87 {
88 public:
89 AtomicInt64(int64_t init = 0) noexcept; ///< Initialize atomic integer
90 AtomicInt64(AtomicInt64 const& src) noexcept;
91 AtomicInt64& operator=(AtomicInt64 const& src) noexcept;
92 ~AtomicInt64() noexcept;
93
94 int64_t get() const noexcept; ///< Returns value of atomic integer
95 int64_t set(int64_t newvalue) noexcept; ///< Updates atomic integer to a new value and returns it previous value
96 int64_t changeIf(int64_t comparand, int64_t newvalue) noexcept; ///< Compares atomic integer with \p comparand and set its to \p newvalue if they match, returns previous value
97
98 int64_t operator++() noexcept; ///< Increments atomic integer and returns its current value
99 int64_t operator++(int) noexcept; ///< Increments atomic integer and returns its previous value
100 int64_t operator--() noexcept; ///< Decrements atomic integer and returns its current value
101 int64_t operator--(int) noexcept; ///< Decrements atomic integer and returns its previous value
102
103 int64_t operator+=(int64_t value) noexcept; ///< Adds number to atomic integer and returns its updated value
104 int64_t operator-=(int64_t value) noexcept; ///< Substracts number to atomic integer and returns its updated value
105
106 private:
107 gate_atomic_int64_t impl;
108 };
109
110 class GATE_CORE_CPP_API AtomicPointer ///< Atomic void* pointer
111 {
112 public:
113 AtomicPointer(void* init = NULL) noexcept; ///< Atomic pointer/address
114 AtomicPointer(AtomicPointer const& src) noexcept;
115 AtomicPointer& operator=(AtomicPointer const& src) noexcept;
116 ~AtomicPointer() noexcept;
117
118 void* get() const noexcept; ///< Returns value of atomic pointer
119 void* set(void* newvalue) noexcept; ///< Updates atomic pointer to a new value and returns it previous value
120 void* changeIf(void* comparand, void* newvalue) noexcept; ///< Updates atomic pointer to \p newvalue only if its original value was equal to \p comparand, returns original value of atomic pointer
121
122 private:
123 gate_atomic_ptr_t impl;
124 };
125
126 template <class T>
127 class GATE_CORE_CPP_API AtomicPtr ///< Template class for typed atomic pointer
128 {
129 private:
130 AtomicPointer impl;
131
132 public:
133 1 AtomicPtr(T* init = NULL) noexcept ///< Initializes atomic pointer
134 1 : impl(static_cast<void*>(init))
135 {
136 1 }
137 1 AtomicPtr(AtomicPtr& src) noexcept
138 1 : impl(static_cast<void*>(src.get()))
139 {
140 1 }
141 1 AtomicPtr& operator=(AtomicPtr const& src) noexcept
142 {
143 1 this->impl.set(src.impl.get());
144 1 return *this;
145 }
146
147 5 T* get() const noexcept ///< Returns current value of atomic pointer
148 {
149 5 return static_cast<T*>(this->impl.get());
150 }
151 2 T* set(T* newvalue) noexcept ///< Updates value of atomic pointer
152 {
153 2 return static_cast<T*>(this->impl.set(static_cast<void*>(newvalue)));
154 }
155 2 T* changeIf(T* comparand, T* newvalue) noexcept ///< updates atomic pointer to \p newvalue only if its original value equals \p comparand, returns original atomic pointer value
156 {
157 2 return static_cast<T*>(this->impl.changeIf(static_cast<void*>(comparand), static_cast<void*>(newvalue)));
158 }
159
160 T* operator->() noexcept ///< Access member of type accessed by atomic pointer
161 {
162 T* ptr = this->get();
163 if (ptr == NULL)
164 {
165 GATEXX_RAISE_ERROR(results::NullPointer);
166 }
167 return ptr;
168 }
169 T& operator*() noexcept ///< Dereferences atomic pointer
170 {
171 T* ptr = this->get();
172 if (ptr == NULL)
173 {
174 GATEXX_RAISE_ERROR(results::NullPointer);
175 }
176 return *ptr;
177 }
178 };
179
180 class GATE_CORE_CPP_API AtomicMutex : private NonCopyable ///< Non-recursive atomic mutex
181 {
182 public:
183 AtomicMutex() noexcept;
184 ~AtomicMutex() noexcept;
185
186 gate_atomic_lock_t* c_impl() noexcept;
187
188 void lock() noexcept; ///< Acquires mutex lock
189 bool lock(uint32_t spinCount) noexcept; ///< Try to acquire mutex lock, but cancel with false if spin-count is reached with lock
190 void unlock() noexcept; ///< Release mutex lock
191
192 private:
193 gate_atomic_lock_t impl;
194 };
195
196 class GATE_CORE_CPP_API AtomicLock : private NonCopyable ///< Atomic RAII mutex-lock
197 {
198 public:
199 AtomicLock(AtomicMutex& mtx) noexcept; ///< Acquires mutex lock
200 AtomicLock(gate_atomic_lock_t& ref_mtx) noexcept;
201 ~AtomicLock() noexcept; ///< Release mutex lock
202
203 private:
204 gate_atomic_lock_t* mutex;
205 };
206
207 class GATE_CORE_CPP_API AtomicRecursiveMutex : private NonCopyable ///< Recursive atomic mutex
208 {
209 public:
210 AtomicRecursiveMutex() noexcept; ///< Acquires mutex lock
211 ~AtomicRecursiveMutex() noexcept;
212
213 gate_atomic_rlock_t* c_impl() noexcept;
214
215 void lock() noexcept; ///< Acquires mutex lock
216 bool lock(uint32_t spinCount) noexcept; ///< Try to acquire mutex lock, but cancel with false if spin-count is reached with lock
217 void unlock() noexcept; ///< Release mutex lock
218
219 private:
220 gate_atomic_rlock_t impl;
221 };
222
223 class GATE_CORE_CPP_API AtomicRecursiveLock : private NonCopyable
224 {
225 public:
226 AtomicRecursiveLock(AtomicRecursiveMutex& mtx) noexcept;
227 AtomicRecursiveLock(gate_atomic_rlock_t& ref_mtx) noexcept;
228 ~AtomicRecursiveLock() noexcept;
229
230 private:
231 gate_atomic_rlock_t* mutex;
232 };
233
234 class GATE_CORE_CPP_API AtomicCallOnce : private NonCopyable
235 {
236 public:
237 AtomicCallOnce() noexcept;
238 ~AtomicCallOnce() noexcept;
239 void operator()(void (*func)(void));
240
241 private:
242 gate_atomic_flag_t state;
243 };
244
245 class GATE_CORE_CPP_API AtomicCallOnceEx : private NonCopyable
246 {
247 public:
248 AtomicCallOnceEx() noexcept;
249 ~AtomicCallOnceEx() noexcept;
250 void operator()(void (*func)(void));
251
252 private:
253 gate_atomic_flag_t state;
254 };
255
256 } // end of namespace gate
257
258 #endif
259