UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Queue.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 "HAL/PlatformMisc.h"
9#include <type_traits>
10
11// WARNING: This queue is planned for deprecation in favor of TSpscQueue or TMpscQueue
12
16enum class EQueueMode
17{
19 Mpsc,
20
22 Spsc,
23
26};
27
28
46template<typename T, EQueueMode Mode = EQueueMode::Spsc>
47class TQueue
48{
49public:
50 using FElementType = T;
51
54 {
55 Head = Tail = new TNode();
56 }
57
60 {
61 while (Tail != nullptr)
62 {
63 TNode* Node = Tail;
64 Tail = Tail->NextNode;
65
66 delete Node;
67 }
68 }
69
71
81 {
82 TNode* Popped = Tail->NextNode;
83
84 if (Popped == nullptr)
85 {
86 return false;
87 }
88
89 if constexpr (Mode != EQueueMode::SingleThreaded)
90 {
91 TSAN_AFTER(&Tail->NextNode);
92 }
93
94 OutItem = MoveTemp(Popped->Item);
95
96 TNode* OldTail = Tail;
97 Tail = Popped;
98 Tail->Item = FElementType();
99 delete OldTail;
100
101 return true;
102 }
103
110 void Empty()
111 {
112 while (Pop());
113 }
114
123 bool Enqueue(const FElementType& Item)
124 {
125 TNode* NewNode = new TNode(Item);
126
127 if (NewNode == nullptr)
128 {
129 return false;
130 }
131
132 TNode* OldHead;
133
134 if constexpr (Mode == EQueueMode::Mpsc)
135 {
136 OldHead = (TNode*)FPlatformAtomics::InterlockedExchangePtr((void**)&Head, NewNode);
137 TSAN_BEFORE(&OldHead->NextNode);
138 FPlatformAtomics::InterlockedExchangePtr((void**)&OldHead->NextNode, NewNode);
139 }
140 else
141 {
142 OldHead = Head;
143 Head = NewNode;
144
145 if constexpr (Mode == EQueueMode::Spsc)
146 {
147 TSAN_BEFORE(&OldHead->NextNode);
149 }
150
151 OldHead->NextNode = NewNode;
152 }
153
154 return true;
155 }
156
166 {
167 TNode* NewNode = new TNode(MoveTemp(Item));
168
169 if (NewNode == nullptr)
170 {
171 return false;
172 }
173
174 TNode* OldHead;
175
176 if constexpr (Mode == EQueueMode::Mpsc)
177 {
178 OldHead = (TNode*)FPlatformAtomics::InterlockedExchangePtr((void**)&Head, NewNode);
179 TSAN_BEFORE(&OldHead->NextNode);
180 FPlatformAtomics::InterlockedExchangePtr((void**)&OldHead->NextNode, NewNode);
181 }
182 else
183 {
184 OldHead = Head;
185 Head = NewNode;
186
187 if constexpr (Mode == EQueueMode::Spsc)
188 {
189 TSAN_BEFORE(&OldHead->NextNode);
191 }
192
193 OldHead->NextNode = NewNode;
194 }
195
196 return true;
197 }
198
206 [[nodiscard]] bool IsEmpty() const
207 {
208 return (Tail->NextNode == nullptr);
209 }
210
220 {
221 if (Tail->NextNode == nullptr)
222 {
223 return false;
224 }
225
226 OutItem = Tail->NextNode->Item;
227
228 return true;
229 }
230
240 {
241 if (Tail->NextNode == nullptr)
242 {
243 return nullptr;
244 }
245
246 return &Tail->NextNode->Item;
247 }
248
250 {
251 return const_cast<TQueue*>(this)->Peek();
252 }
253
261 bool Pop()
262 {
263 TNode* Popped = Tail->NextNode;
264
265 if (Popped == nullptr)
266 {
267 return false;
268 }
269
270 if constexpr (Mode != EQueueMode::SingleThreaded)
271 {
272 TSAN_AFTER(&Tail->NextNode);
273 }
274
275 TNode* OldTail = Tail;
276 Tail = Popped;
277 Tail->Item = FElementType();
278 delete OldTail;
279
280 return true;
281 }
282
283private:
284
286 struct TNode;
287 using TNodeVolatilePtr = std::conditional_t<Mode == EQueueMode::SingleThreaded, TNode*, TNode* volatile>;
288
289 struct TNode
290 {
292 TNodeVolatilePtr NextNode = nullptr;
293
295 FElementType Item;
296
298 [[nodiscard]] TNode() = default;
299
301 [[nodiscard]] explicit TNode(const FElementType& InItem)
302 : Item(InItem)
303 {
304 }
305
307 [[nodiscard]] explicit TNode(FElementType&& InItem)
308 : Item(MoveTemp(InItem))
309 {
310 }
311 };
312
314 MS_ALIGN(16) TNodeVolatilePtr Head GCC_ALIGN(16);
315
317 TNode* Tail;
318};
#define GCC_ALIGN(n)
Definition AndroidPlatform.h:163
#define TSAN_AFTER(Addr)
Definition CoreMiscDefines.h:146
#define TSAN_BEFORE(Addr)
Definition CoreMiscDefines.h:145
EQueueMode
Definition Queue.h:17
#define MS_ALIGN(n)
Definition Platform.h:916
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
Definition Queue.h:48
bool Pop()
Definition Queue.h:261
bool Peek(FElementType &OutItem) const
Definition Queue.h:219
UE_FORCEINLINE_HINT const FElementType * Peek() const
Definition Queue.h:249
TQueue()
Definition Queue.h:53
bool IsEmpty() const
Definition Queue.h:206
UE_NONCOPYABLE(TQueue)
bool Enqueue(FElementType &&Item)
Definition Queue.h:165
~TQueue()
Definition Queue.h:59
T FElementType
Definition Queue.h:50
bool Enqueue(const FElementType &Item)
Definition Queue.h:123
bool Dequeue(FElementType &OutItem)
Definition Queue.h:80
void Empty()
Definition Queue.h:110
FElementType * Peek()
Definition Queue.h:239
static UE_FORCEINLINE_HINT void MemoryBarrier()
Definition AndroidPlatformMisc.h:249