UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Atomic.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
9#include "Traits/IntType.h"
10#include <atomic>
11
13// `TAtomic` is planned for deprecation. Please use `std::atomic`
15
16template <typename T>
18
19template <typename ElementType>
21
22template <typename ElementType, typename DiffType>
24
25template <typename ElementType>
27
28template <typename ElementType>
30
31enum class EMemoryOrder
32{
33 // Provides no guarantees that the operation will be ordered relative to any other operation.
34 Relaxed,
35
36 // Establishes a single total order of all other atomic operations marked with this.
38
39 Count
40};
41
43{
44 template <int Size>
46 {
47 enum { Value = (Size == 1) || (Size == 2) || (Size == 4) || (Size == 8) };
48 };
49
50 template <typename T>
52
53 template <typename T> struct TIsVoidPointer { static constexpr bool Value = false; };
54 template <> struct TIsVoidPointer< void*> { static constexpr bool Value = true; };
55 template <> struct TIsVoidPointer<const void*> { static constexpr bool Value = true; };
56 template <> struct TIsVoidPointer< volatile void*> { static constexpr bool Value = true; };
57 template <> struct TIsVoidPointer<const volatile void*> { static constexpr bool Value = true; };
58
59 template <typename T>
60 FORCEINLINE T LoadRelaxed(const volatile T* Element)
61 {
62 #ifdef __clang__
65 #else
66 auto Result = *(volatile TUnderlyingIntegerType_T<T>*)Element;
67 #endif
68 return *(const T*)&Result;
69 }
70
71 template <typename T>
72 FORCEINLINE T Load(const volatile T* Element)
73 {
74 auto Result = FPlatformAtomics::AtomicRead((volatile TUnderlyingIntegerType_T<T>*)Element);
75 return *(const T*)&Result;
76 }
77
78 template <typename T>
79 FORCEINLINE void StoreRelaxed(const volatile T* Element, T Value)
80 {
81 #ifdef __clang__
83 #else
85 #endif
86 }
87
88 template <typename T>
89 FORCEINLINE void Store(const volatile T* Element, T Value)
90 {
91 FPlatformAtomics::InterlockedExchange((volatile TUnderlyingIntegerType_T<T>*)Element, *(const TUnderlyingIntegerType_T<T>*)&Value);
92 }
93
94 template <typename T>
95 FORCEINLINE T Exchange(volatile T* Element, T Value)
96 {
97 auto Result = FPlatformAtomics::InterlockedExchange((volatile TUnderlyingIntegerType_T<T>*)Element, *(const TUnderlyingIntegerType_T<T>*)&Value);
98 return *(const T*)&Result;
99 }
100
101 template <typename T>
102 FORCEINLINE T IncrementExchange(volatile T* Element)
103 {
104 auto Result = FPlatformAtomics::InterlockedIncrement((volatile TUnderlyingIntegerType_T<T>*)Element) - 1;
105 return *(const T*)&Result;
106 }
107
108 template <typename T>
109 FORCEINLINE T* IncrementExchange(T* volatile* Element)
110 {
111 auto Result = FPlatformAtomics::InterlockedAdd((volatile TUnderlyingIntegerType_T<T*>*)Element, sizeof(T));
112 return *(T* const*)&Result;
113 }
114
115 template <typename T, typename DiffType>
116 FORCEINLINE T AddExchange(volatile T* Element, DiffType Diff)
117 {
118 auto Result = FPlatformAtomics::InterlockedAdd((volatile TUnderlyingIntegerType_T<T>*)Element, (TUnderlyingIntegerType_T<T>)Diff);
119 return *(const T*)&Result;
120 }
121
122 template <typename T, typename DiffType>
123 FORCEINLINE T* AddExchange(T* volatile* Element, DiffType Diff)
124 {
125 auto Result = FPlatformAtomics::InterlockedAdd((volatile TUnderlyingIntegerType_T<T*>*)Element, (TUnderlyingIntegerType_T<T*>)(Diff * sizeof(T)));
126 return *(T* const*)&Result;
127 }
128
129 template <typename T>
130 FORCEINLINE T DecrementExchange(volatile T* Element)
131 {
132 auto Result = FPlatformAtomics::InterlockedDecrement((volatile TUnderlyingIntegerType_T<T>*)Element) + 1;
133 return *(const T*)&Result;
134 }
135
136 template <typename T>
137 FORCEINLINE T* DecrementExchange(T* volatile* Element)
138 {
139 auto Result = FPlatformAtomics::InterlockedAdd((volatile TUnderlyingIntegerType_T<T*>*)Element, -(TUnderlyingIntegerType_T<T*>)sizeof(T));
140 return *(T* const*)&Result;
141 }
142
143 template <typename T, typename DiffType>
144 FORCEINLINE T SubExchange(volatile T* Element, DiffType Diff)
145 {
146 auto Result = FPlatformAtomics::InterlockedAdd((volatile TUnderlyingIntegerType_T<T>*)Element, -(TUnderlyingIntegerType_T<T>)Diff);
147 return *(const T*)&Result;
148 }
149
150 template <typename T, typename DiffType>
151 FORCEINLINE T* SubExchange(T* volatile* Element, DiffType Diff)
152 {
153 auto Result = FPlatformAtomics::InterlockedAdd((volatile TUnderlyingIntegerType_T<T*>*)Element, -(TUnderlyingIntegerType_T<T*>)(Diff * sizeof(T)));
154 return *(T* const*)&Result;
155 }
156
157 template <typename T>
158 FORCEINLINE T CompareExchange(volatile T* Element, T ExpectedValue, T NewValue)
159 {
160 auto Result = FPlatformAtomics::InterlockedCompareExchange((volatile TUnderlyingIntegerType_T<T>*)Element, *(const TUnderlyingIntegerType_T<T>*)&NewValue, *(const TUnderlyingIntegerType_T<T>*)&ExpectedValue);
161 return *(const T*)&Result;
162 }
163
164 template <typename T>
165 FORCEINLINE T AndExchange(volatile T* Element, T AndValue)
166 {
167 auto Result = FPlatformAtomics::InterlockedAnd((volatile TUnderlyingIntegerType_T<T>*)Element, (TUnderlyingIntegerType_T<T>)AndValue);
168 return *(const T*)&Result;
169 }
170
171 template <typename T>
172 FORCEINLINE T OrExchange(volatile T* Element, T OrValue)
173 {
174 auto Result = FPlatformAtomics::InterlockedOr((volatile TUnderlyingIntegerType_T<T>*)Element, (TUnderlyingIntegerType_T<T>)OrValue);
175 return *(const T*)&Result;
176 }
177
178 template <typename T>
179 FORCEINLINE T XorExchange(volatile T* Element, T XorValue)
180 {
181 auto Result = FPlatformAtomics::InterlockedXor((volatile TUnderlyingIntegerType_T<T>*)Element, (TUnderlyingIntegerType_T<T>)XorValue);
182 return *(const T*)&Result;
183 }
184
185 template <typename T, bool bIsVoidPointer, bool bIsIntegral, bool bCanUsePlatformAtomics>
187 {
189 };
190
191 template <typename T>
193 {
194 static_assert(sizeof(T) == 0, "TAtomic of this size are not currently supported");
196 };
197
198 template <typename T>
199 struct TAtomicBaseType<T*, false, false, true>
200 {
202 };
203
204 template <typename T>
206 {
208 };
209
212}
213
214// Basic storage and implementation - only allows getting and setting via platform atomics.
215template <typename T>
216struct
218{
219public:
228 {
229 return Element.load(ToStd(Order));
230 }
231
239 {
240 Element.store(Value, ToStd(Order));
241 }
242
251 {
252 return Element.exchange(Value);
253 }
254
277 FORCEINLINE bool CompareExchange(T& Expected, T Value)
278 {
279 return Element.compare_exchange_strong(Expected, Value);
280 }
281
282protected:
283 TAtomicBase_Basic() = default;
284
286 : Element(Value)
287 {
288 }
289
290 std::atomic<T> Element;
291
292private:
293 static std::memory_order ToStd(EMemoryOrder Order)
294 {
295 std::memory_order Map[(int)EMemoryOrder::Count] = { std::memory_order_relaxed, std::memory_order_seq_cst };
296 return Map[(int)Order];
297 }
298};
299
300// TODO : basic storage and getting and setting, but the element is protected by a mutex instead of using platform atomics.
301// Also, we may not want to do this ever.
302template <typename T>
303struct TAtomicBase_Mutex;
304
305// Arithmetic atomic implementation - used by both pointers and integral types in addition to getting and setting.
306template <typename T, typename DiffType>
308{
309public:
316 {
317 return this->Element.fetch_add(1) + 1;
318 }
319
326 {
327 return this->Element.fetch_add(1);
328 }
329
338 {
339 return this->Element.fetch_add(Value) + Value;
340 }
341
348 {
349 return this->Element.fetch_sub(1) - 1;
350 }
351
358 {
359 return this->Element.fetch_sub(1);
360 }
361
370 {
371 return this->Element.fetch_sub(Value) - Value;
372 }
373
380 {
381 return this->Element.fetch_add(1);
382 }
383
390 {
391 return this->Element.fetch_sub(1);
392 }
393
402 {
403 return this->Element.fetch_add(Value);
404 }
405
414 {
415 return this->Element.fetch_sub(Value);
416 }
417
418protected:
420
423 {
424 }
425};
426
427// Pointer atomic implementation - allows arithmetic with PTRINT.
428template <typename T>
430{
431protected:
433
436 {
437 }
438};
439
440// Integral atomic implementation - allows arithmetic and bitwise operations.
441template <typename T>
443{
444public:
453 {
454 return this->Element.fetch_and(Value) & Value;
455 }
456
465 {
466 return this->Element.fetch_or(Value) | Value;
467 }
468
477 {
478 return this->Element.fetch_xor(Value) ^ Value;
479 }
480
489 {
490 return this->Element.fetch_and(Value);
491 }
492
501 {
502 return this->Element.fetch_or(Value);
503 }
504
513 {
514 return this->Element.fetch_xor(Value);
515 }
516
517
518protected:
520
523 {
524 }
525};
526
536template <typename T>
538{
539 static_assert(TIsTrivial<T>::Value, "TAtomic is only usable with trivial types");
540
541public:
542 using ElementType = T;
543
547 FORCEINLINE TAtomic() = default;
548
556 constexpr TAtomic(T Arg)
557 : UE::Core::Private::Atomic::TAtomicBaseType_T<T>(Arg)
558 {
559 }
560
566 FORCEINLINE operator T() const
567 {
568 return this->Load();
569 }
570
579 {
580 this->Exchange(Value);
581 return Value;
582 }
583
584private:
585 // Non-copyable and non-movable
586 TAtomic(TAtomic&&) = delete;
587 TAtomic(const TAtomic&) = delete;
588 TAtomic& operator=(TAtomic&&) = delete;
589 TAtomic& operator=(const TAtomic&) = delete;
590};
OODEFFUNC typedef void(OODLE_CALLBACK t_fp_OodleCore_Plugin_Free)(void *ptr)
#define FORCEINLINE
Definition AndroidPlatform.h:140
FPlatformTypes::PTRINT PTRINT
A signed integer the same size as a pointer.
Definition Platform.h:1148
EMemoryOrder
Definition Atomic.h:32
@ SequentiallyConsistent
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
return true
Definition ExternalRpcRegistry.cpp:601
typename TSignedIntType< NumBytes >::Type TSignedIntType_T
Definition IntType.h:25
UE_REWRITE constexpr void Exchange(T &A, T &B)
Definition UnrealTemplate.h:627
uint32 Size
Definition VulkanMemory.cpp:4034
Definition Core.Build.cs:8
Definition Atomic.h:538
constexpr TAtomic(T Arg)
Definition Atomic.h:556
T ElementType
Definition Atomic.h:542
FORCEINLINE T operator=(T Value)
Definition Atomic.h:578
FORCEINLINE TAtomic()=default
Definition OverriddenPropertySet.cpp:45
Definition Atomic.h:43
typename TAtomicBaseType< T, bIsVoidPointer, bIsIntegral, bCanUsePlatformAtomics >::Type TAtomicBaseType_T
Definition Atomic.h:211
FORCEINLINE T IncrementExchange(volatile T *Element)
Definition Atomic.h:102
FORCEINLINE T CompareExchange(volatile T *Element, T ExpectedValue, T NewValue)
Definition Atomic.h:158
FORCEINLINE T XorExchange(volatile T *Element, T XorValue)
Definition Atomic.h:179
FORCEINLINE void Store(const volatile T *Element, T Value)
Definition Atomic.h:89
TSignedIntType_T< sizeof(T)> TUnderlyingIntegerType_T
Definition Atomic.h:51
FORCEINLINE T OrExchange(volatile T *Element, T OrValue)
Definition Atomic.h:172
FORCEINLINE T SubExchange(volatile T *Element, DiffType Diff)
Definition Atomic.h:144
FORCEINLINE T AddExchange(volatile T *Element, DiffType Diff)
Definition Atomic.h:116
FORCEINLINE T LoadRelaxed(const volatile T *Element)
Definition Atomic.h:60
FORCEINLINE T DecrementExchange(volatile T *Element)
Definition Atomic.h:130
FORCEINLINE void StoreRelaxed(const volatile T *Element, T Value)
Definition Atomic.h:79
FORCEINLINE T AndExchange(volatile T *Element, T AndValue)
Definition Atomic.h:165
FORCEINLINE T Exchange(volatile T *Element, T Value)
Definition Atomic.h:95
Definition AdvancedWidgetsModule.cpp:13
@ false
Definition radaudio_common.h:23
Definition Atomic.h:308
FORCEINLINE T operator-=(DiffType Value)
Definition Atomic.h:369
FORCEINLINE T SubExchange(DiffType Value)
Definition Atomic.h:413
FORCEINLINE T AddExchange(DiffType Value)
Definition Atomic.h:401
FORCEINLINE T operator++(int)
Definition Atomic.h:325
FORCEINLINE T operator+=(DiffType Value)
Definition Atomic.h:337
FORCEINLINE T DecrementExchange()
Definition Atomic.h:389
constexpr TAtomicBase_Arithmetic(T Value)
Definition Atomic.h:421
FORCEINLINE T IncrementExchange()
Definition Atomic.h:379
FORCEINLINE T operator--(int)
Definition Atomic.h:357
TAtomicBase_Arithmetic()=default
FORCEINLINE T operator++()
Definition Atomic.h:315
FORCEINLINE T operator--()
Definition Atomic.h:347
Definition Atomic.h:218
FORCEINLINE void Store(T Value, EMemoryOrder Order=EMemoryOrder::SequentiallyConsistent)
Definition Atomic.h:238
FORCEINLINE T Load(EMemoryOrder Order=EMemoryOrder::SequentiallyConsistent) const
Definition Atomic.h:227
FORCEINLINE T Exchange(T Value)
Definition Atomic.h:250
constexpr TAtomicBase_Basic(T Value)
Definition Atomic.h:285
TAtomicBase_Basic()=default
FORCEINLINE bool CompareExchange(T &Expected, T Value)
Definition Atomic.h:277
std::atomic< T > Element
Definition Atomic.h:290
Definition Atomic.h:443
FORCEINLINE T XorExchange(const T Value)
Definition Atomic.h:512
FORCEINLINE T operator&=(const T Value)
Definition Atomic.h:452
FORCEINLINE T AndExchange(const T Value)
Definition Atomic.h:488
FORCEINLINE T operator|=(const T Value)
Definition Atomic.h:464
FORCEINLINE T operator^=(const T Value)
Definition Atomic.h:476
FORCEINLINE T OrExchange(const T Value)
Definition Atomic.h:500
TAtomicBase_Integral()=default
constexpr TAtomicBase_Integral(T Value)
Definition Atomic.h:521
Definition Atomic.h:20
Definition Atomic.h:430
constexpr TAtomicBase_Pointer(T Value)
Definition Atomic.h:434
TAtomicBase_Pointer()=default
Definition IsIntegral.h:12
Definition IsTrivial.h:15
static constexpr bool Value
Definition Atomic.h:53