UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
WindowsPlatformAtomics.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
8#include <intrin.h>
9
10#include <atomic>
11
12template <typename T>
14 static_assert(sizeof(T) == sizeof(std::atomic<T>), "Unexpected atomic size");
15 static_assert( alignof(T) == alignof(std::atomic<T>), "Unexpected atomic alignment");
16};
17
22
28{
29 static_assert(sizeof(int8) == sizeof(char) && alignof(int8) == alignof(char), "int8 must be compatible with char");
30 static_assert(sizeof(int16) == sizeof(short) && alignof(int16) == alignof(short), "int16 must be compatible with short");
31 static_assert(sizeof(int32) == sizeof(long) && alignof(int32) == alignof(long), "int32 must be compatible with long");
32 static_assert(sizeof(int64) == sizeof(long long) && alignof(int64) == alignof(long long), "int64 must be compatible with long long");
33
35 {
36 return (int8)::_InterlockedExchangeAdd8((char*)Value, 1) + 1;
37 }
38
40 {
41 return (int16)::_InterlockedIncrement16((short*)Value);
42 }
43
45 {
46 return (int32)::_InterlockedIncrement((long*)Value);
47 }
48
50 {
51 #if PLATFORM_64BITS
52 return (int64)::_InterlockedIncrement64((long long*)Value);
53 #else
54 // No explicit instruction for 64-bit atomic increment on 32-bit processors; has to be implemented in terms of CMPXCHG8B
55 for (;;)
56 {
57 int64 OldValue = *Value;
58 if (_InterlockedCompareExchange64(Value, OldValue + 1, OldValue) == OldValue)
59 {
60 return OldValue + 1;
61 }
62 }
63 #endif
64 }
65
67 {
68 return (int8)::_InterlockedExchangeAdd8((char*)Value, -1) - 1;
69 }
70
72 {
73 return (int16)::_InterlockedDecrement16((short*)Value);
74 }
75
77 {
78 return (int32)::_InterlockedDecrement((long*)Value);
79 }
80
82 {
83 #if PLATFORM_64BITS
84 return (int64)::_InterlockedDecrement64((long long*)Value);
85 #else
86 // No explicit instruction for 64-bit atomic decrement on 32-bit processors; has to be implemented in terms of CMPXCHG8B
87 for (;;)
88 {
89 int64 OldValue = *Value;
90 if (_InterlockedCompareExchange64(Value, OldValue - 1, OldValue) == OldValue)
91 {
92 return OldValue - 1;
93 }
94 }
95 #endif
96 }
97
98 static FORCEINLINE int8 InterlockedAdd( volatile int8* Value, int8 Amount )
99 {
100 return (int8)::_InterlockedExchangeAdd8((char*)Value, (char)Amount);
101 }
102
103 static FORCEINLINE int16 InterlockedAdd( volatile int16* Value, int16 Amount )
104 {
105 return (int16)::_InterlockedExchangeAdd16((short*)Value, (short)Amount);
106 }
107
108 static FORCEINLINE int32 InterlockedAdd( volatile int32* Value, int32 Amount )
109 {
110 return (int32)::_InterlockedExchangeAdd((long*)Value, (long)Amount);
111 }
112
113 static FORCEINLINE int64 InterlockedAdd( volatile int64* Value, int64 Amount )
114 {
115 #if PLATFORM_64BITS
117 #else
118 // No explicit instruction for 64-bit atomic add on 32-bit processors; has to be implemented in terms of CMPXCHG8B
119 for (;;)
120 {
121 int64 OldValue = *Value;
122 if (_InterlockedCompareExchange64(Value, OldValue + Amount, OldValue) == OldValue)
123 {
124 return OldValue;
125 }
126 }
127 #endif
128 }
129
131 {
132 return (int8)::_InterlockedExchange8((char*)Value, (char)Exchange);
133 }
134
136 {
137 return (int16)::_InterlockedExchange16((short*)Value, (short)Exchange);
138 }
139
141 {
142 return (int32)::_InterlockedExchange((long*)Value, (long)Exchange);
143 }
144
146 {
147 #if PLATFORM_64BITS
148 return (int64)::_InterlockedExchange64((long long*)Value, (long long)Exchange);
149 #else
150 // No explicit instruction for 64-bit atomic exchange on 32-bit processors; has to be implemented in terms of CMPXCHG8B
151 for (;;)
152 {
153 int64 OldValue = *Value;
154 if (_InterlockedCompareExchange64(Value, Exchange, OldValue) == OldValue)
155 {
156 return OldValue;
157 }
158 }
159 #endif
160 }
161
162 static FORCEINLINE void* InterlockedExchangePtr( void*volatile* Dest, void* Exchange )
163 {
164 #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
165 if (IsAligned(Dest, alignof(void*)) == false)
166 {
167 HandleAtomicsFailure(TEXT("InterlockedExchangePointer requires Dest pointer to be aligned to %d bytes"), (int)alignof(void*));
168 }
169 #endif
170
171 return ::_InterlockedExchangePointer(Dest, Exchange);
172 }
173
175 {
176 return (int8)::_InterlockedCompareExchange8((char*)Dest, (char)Exchange, (char)Comparand);
177 }
178
180 {
181 return (int16)::_InterlockedCompareExchange16((short*)Dest, (short)Exchange, (short)Comparand);
182 }
183
185 {
186 return (int32)::_InterlockedCompareExchange((long*)Dest, (long)Exchange, (long)Comparand);
187 }
188
190 {
191 #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
192 if (IsAligned(Dest, alignof(int64)) == false)
193 {
194 HandleAtomicsFailure(TEXT("InterlockedCompareExchange int64 requires Dest pointer to be aligned to %d bytes"), (int)alignof(int64));
195 }
196 #endif
197
199 }
200
202 {
203 return (int8)::_InterlockedAnd8((volatile char*)Value, (char)AndValue);
204 }
205
207 {
208 return (int16)::_InterlockedAnd16((volatile short*)Value, (short)AndValue);
209 }
210
212 {
213 return (int32)::_InterlockedAnd((volatile long*)Value, (long)AndValue);
214 }
215
217 {
218 #if PLATFORM_64BITS
219 return (int64)::_InterlockedAnd64((volatile long long*)Value, (long long)AndValue);
220 #else
221 // No explicit instruction for 64-bit atomic and on 32-bit processors; has to be implemented in terms of CMPXCHG8B
222 for (;;)
223 {
224 const int64 OldValue = *Value;
225 if (_InterlockedCompareExchange64(Value, OldValue & AndValue, OldValue) == OldValue)
226 {
227 return OldValue;
228 }
229 }
230 #endif
231 }
232
234 {
235 return (int8)::_InterlockedOr8((volatile char*)Value, (char)OrValue);
236 }
237
239 {
240 return (int16)::_InterlockedOr16((volatile short*)Value, (short)OrValue);
241 }
242
244 {
245 return (int32)::_InterlockedOr((volatile long*)Value, (long)OrValue);
246 }
247
249 {
250 #if PLATFORM_64BITS
251 return (int64)::_InterlockedOr64((volatile long long*)Value, (long long)OrValue);
252 #else
253 // No explicit instruction for 64-bit atomic or on 32-bit processors; has to be implemented in terms of CMPXCHG8B
254 for (;;)
255 {
256 const int64 OldValue = *Value;
257 if (_InterlockedCompareExchange64(Value, OldValue | OrValue, OldValue) == OldValue)
258 {
259 return OldValue;
260 }
261 }
262 #endif
263 }
264
266 {
267 return (int8)::_InterlockedXor8((volatile char*)Value, (char)XorValue);
268 }
269
271 {
272 return (int16)::_InterlockedXor16((volatile short*)Value, (short)XorValue);
273 }
274
276 {
277 return (int32)::_InterlockedXor((volatile long*)Value, (int32)XorValue);
278 }
279
281 {
282 #if PLATFORM_64BITS
283 return (int64)::_InterlockedXor64((volatile long long*)Value, (long long)XorValue);
284 #else
285 // No explicit instruction for 64-bit atomic xor on 32-bit processors; has to be implemented in terms of CMPXCHG8B
286 for (;;)
287 {
288 const int64 OldValue = *Value;
289 if (_InterlockedCompareExchange64(Value, OldValue ^ XorValue, OldValue) == OldValue)
290 {
291 return OldValue;
292 }
293 }
294 #endif
295 }
296
297 static FORCEINLINE int8 AtomicRead(volatile const int8* Src)
298 {
299 return ((std::atomic<int8>*)(Src))->load();
300 }
301
302 static FORCEINLINE int16 AtomicRead(volatile const int16* Src)
303 {
304 return ((std::atomic<int16>*)(Src))->load();
305 }
306
307 static FORCEINLINE int32 AtomicRead(volatile const int32* Src)
308 {
309 return ((std::atomic<int32>*)(Src))->load();
310 }
311
312 static FORCEINLINE int64 AtomicRead(volatile const int64* Src)
313 {
314 return ((std::atomic<int64>*)(Src))->load();
315 }
316
317 static FORCEINLINE int8 AtomicRead_Relaxed(volatile const int8* Src)
318 {
319 return ((std::atomic<int8>*)(Src))->load(std::memory_order_relaxed);
320 }
321
322 static FORCEINLINE int16 AtomicRead_Relaxed(volatile const int16* Src)
323 {
324 return ((std::atomic<int16>*)(Src))->load(std::memory_order_relaxed);
325 }
326
327 static FORCEINLINE int32 AtomicRead_Relaxed(volatile const int32* Src)
328 {
329 return ((std::atomic<int32>*)(Src))->load(std::memory_order_relaxed);
330 }
331
332 static FORCEINLINE int64 AtomicRead_Relaxed(volatile const int64* Src)
333 {
334 #if PLATFORM_64BITS
335 return ((std::atomic<int64>*)(Src))->load(std::memory_order_relaxed);
336 #else
337 return InterlockedCompareExchange((volatile int64*)Src, 0, 0);
338 #endif
339 }
340
341 static FORCEINLINE void AtomicStore(volatile int8* Src, int8 Val)
342 {
343 ((std::atomic<int8>*)(Src))->store(Val);
344 }
345
346 static FORCEINLINE void AtomicStore(volatile int16* Src, int16 Val)
347 {
348 ((std::atomic<int16>*)(Src))->store(Val);
349 }
350
351 static FORCEINLINE void AtomicStore(volatile int32* Src, int32 Val)
352 {
353 ((std::atomic<int32>*)(Src))->store(Val);
354 }
355
356 static FORCEINLINE void AtomicStore(volatile int64* Src, int64 Val)
357 {
358 ((std::atomic<int64>*)(Src))->store(Val);
359 }
360
361 static FORCEINLINE void AtomicStore_Relaxed(volatile int8* Src, int8 Val)
362 {
363 ((std::atomic<int8>*)(Src))->store(Val, std::memory_order_relaxed);
364 }
365
366 static FORCEINLINE void AtomicStore_Relaxed(volatile int16* Src, int16 Val)
367 {
368 ((std::atomic<int16>*)(Src))->store(Val, std::memory_order_relaxed);
369 }
370
371 static FORCEINLINE void AtomicStore_Relaxed(volatile int32* Src, int32 Val)
372 {
373 ((std::atomic<int32>*)(Src))->store(Val, std::memory_order_relaxed);
374 }
375
376 static FORCEINLINE void AtomicStore_Relaxed(volatile int64* Src, int64 Val)
377 {
378 #if PLATFORM_64BITS
379 ((std::atomic<int64>*)(Src))->store(Val, std::memory_order_relaxed);
380 #else
382 #endif
383 }
384
395#if PLATFORM_HAS_128BIT_ATOMICS
397 {
398#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
399 if (IsAligned(Dest,16) == false)
400 {
401 HandleAtomicsFailure(TEXT("InterlockedCompareExchange128 requires Dest pointer to be aligned to 16 bytes") );
402 }
403 if (IsAligned(Comparand,16) == false)
404 {
405 HandleAtomicsFailure(TEXT("InterlockedCompareExchange128 requires Comparand pointer to be aligned to 16 bytes") );
406 }
407#endif
408
409 return ::_InterlockedCompareExchange128((int64 volatile *)Dest, Exchange.High, Exchange.Low, (int64*)Comparand) == 1;
410 }
414 static FORCEINLINE void AtomicRead128(const volatile FInt128* Src, FInt128* OutResult)
415 {
417 Zero.High = 0;
418 Zero.Low = 0;
419 *OutResult = Zero;
421 }
422
423#endif // PLATFORM_HAS_128BIT_ATOMICS
424
425 static FORCEINLINE void* InterlockedCompareExchangePointer( void*volatile* Dest, void* Exchange, void* Comparand )
426 {
427 #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
428 if (IsAligned(Dest, alignof(void*)) == false)
429 {
430 HandleAtomicsFailure(TEXT("InterlockedCompareExchangePointer requires Dest pointer to be aligned to %d bytes"), (int)alignof(void*));
431 }
432 #endif
433
434 return ::_InterlockedCompareExchangePointer(Dest, Exchange, Comparand);
435 }
436
445
446protected:
454 static CORE_API void HandleAtomicsFailure( const TCHAR* InFormat, ... );
455};
456
457#ifdef __clang__
459
460typedef FClangPlatformAtomics FPlatformAtomics;
461#else
463#endif // __clang__
#define FORCEINLINE
Definition AndroidPlatform.h:140
FPlatformTypes::int16 int16
A 16-bit signed integer.
Definition Platform.h:1123
FPlatformTypes::int8 int8
An 8-bit signed integer.
Definition Platform.h:1121
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define WINDOWS_PF_COMPARE_EXCHANGE128
Definition MinimalWindowsApi.h:55
float Val(const FString &Value)
Definition UnrealMath.cpp:3163
UE_REWRITE constexpr void Exchange(T &A, T &B)
Definition UnrealTemplate.h:627
TStdAtomicSizeAssert< int16 > Assert16
Definition WindowsPlatformAtomics.h:19
FWindowsPlatformAtomics FPlatformAtomics
Definition WindowsPlatformAtomics.h:462
TStdAtomicSizeAssert< int64 > Assert64
Definition WindowsPlatformAtomics.h:21
TStdAtomicSizeAssert< int32 > Assert32
Definition WindowsPlatformAtomics.h:20
TStdAtomicSizeAssert< int8 > Assert8
Definition WindowsPlatformAtomics.h:18
Definition WindowsPlatformAtomics.h:13
MINIMAL_WINDOWS_API BOOL WINAPI IsProcessorFeaturePresent(DWORD ProcessorFeature)
Definition GenericPlatformAtomics.h:26
static bool IsAligned(const volatile void *Ptr, const uint32 Alignment=sizeof(void *))
Definition GenericPlatformAtomics.h:326
Definition WindowsPlatformAtomics.h:28
static FORCEINLINE void AtomicStore_Relaxed(volatile int32 *Src, int32 Val)
Definition WindowsPlatformAtomics.h:371
static FORCEINLINE int8 InterlockedAdd(volatile int8 *Value, int8 Amount)
Definition WindowsPlatformAtomics.h:98
static FORCEINLINE int32 InterlockedExchange(volatile int32 *Value, int32 Exchange)
Definition WindowsPlatformAtomics.h:140
static FORCEINLINE int32 InterlockedOr(volatile int32 *Value, const int32 OrValue)
Definition WindowsPlatformAtomics.h:243
static FORCEINLINE int32 InterlockedIncrement(volatile int32 *Value)
Definition WindowsPlatformAtomics.h:44
static FORCEINLINE int8 InterlockedOr(volatile int8 *Value, const int8 OrValue)
Definition WindowsPlatformAtomics.h:233
static FORCEINLINE int8 InterlockedAnd(volatile int8 *Value, const int8 AndValue)
Definition WindowsPlatformAtomics.h:201
static FORCEINLINE int32 InterlockedDecrement(volatile int32 *Value)
Definition WindowsPlatformAtomics.h:76
static FORCEINLINE int8 AtomicRead_Relaxed(volatile const int8 *Src)
Definition WindowsPlatformAtomics.h:317
static FORCEINLINE int8 AtomicRead(volatile const int8 *Src)
Definition WindowsPlatformAtomics.h:297
static FORCEINLINE int64 InterlockedXor(volatile int64 *Value, const int64 XorValue)
Definition WindowsPlatformAtomics.h:280
static FORCEINLINE int32 AtomicRead_Relaxed(volatile const int32 *Src)
Definition WindowsPlatformAtomics.h:327
static FORCEINLINE void * InterlockedCompareExchangePointer(void *volatile *Dest, void *Exchange, void *Comparand)
Definition WindowsPlatformAtomics.h:425
static FORCEINLINE void AtomicStore(volatile int8 *Src, int8 Val)
Definition WindowsPlatformAtomics.h:341
static FORCEINLINE int16 InterlockedXor(volatile int16 *Value, const int16 XorValue)
Definition WindowsPlatformAtomics.h:270
static FORCEINLINE int16 InterlockedAdd(volatile int16 *Value, int16 Amount)
Definition WindowsPlatformAtomics.h:103
static FORCEINLINE int64 InterlockedOr(volatile int64 *Value, const int64 OrValue)
Definition WindowsPlatformAtomics.h:248
static FORCEINLINE int16 InterlockedDecrement(volatile int16 *Value)
Definition WindowsPlatformAtomics.h:71
static FORCEINLINE int64 InterlockedExchange(volatile int64 *Value, int64 Exchange)
Definition WindowsPlatformAtomics.h:145
static FORCEINLINE int64 InterlockedAdd(volatile int64 *Value, int64 Amount)
Definition WindowsPlatformAtomics.h:113
static FORCEINLINE int8 InterlockedXor(volatile int8 *Value, const int8 XorValue)
Definition WindowsPlatformAtomics.h:265
static FORCEINLINE int8 InterlockedCompareExchange(volatile int8 *Dest, int8 Exchange, int8 Comparand)
Definition WindowsPlatformAtomics.h:174
static FORCEINLINE int64 AtomicRead(volatile const int64 *Src)
Definition WindowsPlatformAtomics.h:312
static FORCEINLINE int32 InterlockedAnd(volatile int32 *Value, const int32 AndValue)
Definition WindowsPlatformAtomics.h:211
static FORCEINLINE int16 InterlockedAnd(volatile int16 *Value, const int16 AndValue)
Definition WindowsPlatformAtomics.h:206
static FORCEINLINE void AtomicStore(volatile int64 *Src, int64 Val)
Definition WindowsPlatformAtomics.h:356
static FORCEINLINE int64 InterlockedCompareExchange(volatile int64 *Dest, int64 Exchange, int64 Comparand)
Definition WindowsPlatformAtomics.h:189
static FORCEINLINE int16 InterlockedIncrement(volatile int16 *Value)
Definition WindowsPlatformAtomics.h:39
static FORCEINLINE void AtomicStore_Relaxed(volatile int64 *Src, int64 Val)
Definition WindowsPlatformAtomics.h:376
static FORCEINLINE int32 InterlockedCompareExchange(volatile int32 *Dest, int32 Exchange, int32 Comparand)
Definition WindowsPlatformAtomics.h:184
static FORCEINLINE int64 AtomicRead_Relaxed(volatile const int64 *Src)
Definition WindowsPlatformAtomics.h:332
static FORCEINLINE void AtomicStore_Relaxed(volatile int16 *Src, int16 Val)
Definition WindowsPlatformAtomics.h:366
static FORCEINLINE int64 InterlockedAnd(volatile int64 *Value, const int64 AndValue)
Definition WindowsPlatformAtomics.h:216
static FORCEINLINE int16 AtomicRead(volatile const int16 *Src)
Definition WindowsPlatformAtomics.h:302
static FORCEINLINE int32 InterlockedAdd(volatile int32 *Value, int32 Amount)
Definition WindowsPlatformAtomics.h:108
static FORCEINLINE int16 AtomicRead_Relaxed(volatile const int16 *Src)
Definition WindowsPlatformAtomics.h:322
static FORCEINLINE void AtomicStore(volatile int32 *Src, int32 Val)
Definition WindowsPlatformAtomics.h:351
static FORCEINLINE int16 InterlockedExchange(volatile int16 *Value, int16 Exchange)
Definition WindowsPlatformAtomics.h:135
static FORCEINLINE int32 InterlockedXor(volatile int32 *Value, const int32 XorValue)
Definition WindowsPlatformAtomics.h:275
static FORCEINLINE void AtomicStore(volatile int16 *Src, int16 Val)
Definition WindowsPlatformAtomics.h:346
static FORCEINLINE int8 InterlockedDecrement(volatile int8 *Value)
Definition WindowsPlatformAtomics.h:66
static FORCEINLINE int16 InterlockedOr(volatile int16 *Value, const int16 OrValue)
Definition WindowsPlatformAtomics.h:238
static FORCEINLINE int64 InterlockedIncrement(volatile int64 *Value)
Definition WindowsPlatformAtomics.h:49
static FORCEINLINE int8 InterlockedExchange(volatile int8 *Value, int8 Exchange)
Definition WindowsPlatformAtomics.h:130
static FORCEINLINE int32 AtomicRead(volatile const int32 *Src)
Definition WindowsPlatformAtomics.h:307
static CORE_API void HandleAtomicsFailure(const TCHAR *InFormat,...)
Definition WindowsPlatformAtomics.cpp:10
static FORCEINLINE int8 InterlockedIncrement(volatile int8 *Value)
Definition WindowsPlatformAtomics.h:34
static FORCEINLINE int16 InterlockedCompareExchange(volatile int16 *Dest, int16 Exchange, int16 Comparand)
Definition WindowsPlatformAtomics.h:179
static FORCEINLINE int64 InterlockedDecrement(volatile int64 *Value)
Definition WindowsPlatformAtomics.h:81
static FORCEINLINE void AtomicStore_Relaxed(volatile int8 *Src, int8 Val)
Definition WindowsPlatformAtomics.h:361
static FORCEINLINE void * InterlockedExchangePtr(void *volatile *Dest, void *Exchange)
Definition WindowsPlatformAtomics.h:162
static FORCEINLINE bool CanUseCompareExchange128()
Definition WindowsPlatformAtomics.h:441