UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
LockFreeList.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
5#include "Containers/Array.h"
7#include "CoreGlobals.h"
8#include "CoreTypes.h"
14#include "Misc/NoopCounter.h"
16#include "Templates/Function.h"
17
18#include <atomic>
19
21
22// what level of checking to perform...normally checkLockFreePointerList but could be ensure or check
23#if 1
24 #define checkLockFreePointerList checkSlow
25#else
26 #if PLATFORM_WINDOWS
27 #pragma warning(disable : 4706)
28 #endif
29 #define checkLockFreePointerList(x) ((x)||((*(char*)3) = 0))
30#endif
31
32#if !UE_BUILD_SHIPPING && !UE_BUILD_TEST
33
36
37 inline void TestCriticalStall()
38 {
40 {
42 }
43 }
44#else
46 {
47 }
48#endif
49
53CORE_API void LockFreeFreeLinks(SIZE_T AllocSize, void* Ptr);
54
55#define MAX_LOCK_FREE_LINKS_AS_BITS (26)
56#define MAX_LOCK_FREE_LINKS (1 << 26)
57
58template<class T, unsigned int MaxTotalItems, unsigned int ItemsPerPage>
60{
61 enum
62 {
63 MaxBlocks = (MaxTotalItems + ItemsPerPage - 1) / ItemsPerPage
64 };
65public:
66
68 {
69 NextIndex.Increment(); // skip the null ptr
70 for (uint32 Index = 0; Index < MaxBlocks; Index++)
71 {
72 Pages[Index] = nullptr;
73 }
74 }
75
77 {
78 uint32 FirstItem = NextIndex.Add(Count);
79 if (FirstItem + Count > MaxTotalItems)
80 {
82 }
83 for (uint32 CurrentItem = FirstItem; CurrentItem < FirstItem + Count; CurrentItem++)
84 {
85 ::new (GetRawItem(CurrentItem)) T();
86 }
87 return FirstItem;
88 }
90 {
91 if (!Index)
92 {
93 return nullptr;
94 }
97 checkLockFreePointerList(Index < (uint32)NextIndex.GetValue() && Index < MaxTotalItems && BlockIndex < MaxBlocks && Pages[BlockIndex]);
98 return Pages[BlockIndex] + SubIndex;
99 }
100
101private:
102 [[nodiscard]] void* GetRawItem(uint32 Index)
103 {
106 checkLockFreePointerList(Index && Index < (uint32)NextIndex.GetValue() && Index < MaxTotalItems && BlockIndex < MaxBlocks);
107 if (!Pages[BlockIndex])
108 {
109 T* NewBlock = (T*)LockFreeAllocLinks(ItemsPerPage * sizeof(T));
111 if (FPlatformAtomics::InterlockedCompareExchangePointer((void**)&Pages[BlockIndex], NewBlock, nullptr) != nullptr)
112 {
113 // we lost discard block
116 }
117 else
118 {
120 }
121 }
122 return (void*)(Pages[BlockIndex] + SubIndex);
123 }
124
126 alignas(PLATFORM_CACHE_LINE_SIZE) T* Pages[MaxBlocks];
127};
128
129
130#define MAX_TagBitsValue (uint64(1) << (64 - MAX_LOCK_FREE_LINKS_AS_BITS))
132
133
134MS_ALIGN(8)
136{
137 // no constructor, intentionally. We need to keep the ABA double counter in tact
138
139 // This should only be used for FIndexedPointer's with no outstanding concurrency.
140 // Not recycled links, for example.
141 void Init()
142 {
143 static_assert(((MAX_LOCK_FREE_LINKS - 1) & MAX_LOCK_FREE_LINKS) == 0, "MAX_LOCK_FREE_LINKS must be a power of two");
144 Ptrs.store(0, std::memory_order_relaxed);
145 }
147 {
149 Ptrs.store(uint64(Ptr) | (CounterAndState << MAX_LOCK_FREE_LINKS_AS_BITS), std::memory_order_relaxed);
150 }
151
153 {
154 return uint32(Ptrs.load(std::memory_order_relaxed) & (MAX_LOCK_FREE_LINKS - 1));
155 }
156
161
163 {
164 return (Ptrs.load(std::memory_order_relaxed) >> MAX_LOCK_FREE_LINKS_AS_BITS);
165 }
166
171
173 {
176 {
177 // this is not expected to be a problem and it is not expected to happen very often. When it does happen, we will sleep as an extra precaution.
179 }
180 }
181
182 template<uint64 TABAInc>
184 {
185 return GetCounterAndState() & (TABAInc - 1);
186 }
187
188 template<uint64 TABAInc>
194
195 inline void AtomicRead(const FIndexedPointer& Other)
196 {
197 checkLockFreePointerList(IsAligned(&Ptrs, 8) && IsAligned(&Other.Ptrs, 8));
198 Ptrs.store(Other.Ptrs.load(std::memory_order_acquire), std::memory_order_relaxed);
200 }
201
203 {
205 uint64 Expected = Comparand.Ptrs.load(std::memory_order_relaxed);
206 return Ptrs.compare_exchange_strong(Expected, Exchange.Ptrs.load(std::memory_order_relaxed), std::memory_order_acq_rel, std::memory_order_relaxed);
207 }
208
210 {
211 return Ptrs.load(std::memory_order_relaxed) == Other.Ptrs.load(std::memory_order_relaxed);
212 }
214 {
215 return Ptrs.load(std::memory_order_relaxed) != Other.Ptrs.load(std::memory_order_relaxed);
216 }
217
218private:
219 std::atomic<uint64> Ptrs;
220
221} GCC_ALIGN(8);
222
224{
226 std::atomic<void*> Payload;
227 std::atomic<uint32> SingleNext;
229
230// there is a version of this code that uses 128 bit atomics to avoid the indirection, that is why we have this policy class at all.
259
260template<int TPaddingForCacheContention, uint64 TABAInc = 1>
262{
264
267 typedef FLockFreeLinkPolicy::TLinkPtr TLinkPtr;
268
269public:
271 {
272 // We want to make sure we have quite a lot of extra counter values to avoid the ABA problem. This could probably be relaxed, but eventually it will be dangerous.
273 // The question is "how many queue operations can a thread starve for".
274 static_assert(MAX_TagBitsValue / TABAInc >= (1 << 23), "risk of ABA problem");
275 static_assert((TABAInc & (TABAInc - 1)) == 0, "must be power of two");
276 Reset();
277 }
278
279 void Reset()
280 {
281 Head.Init();
282 }
283
284 void Push(TLinkPtr Item)
285 {
286 while (true)
287 {
289 LocalHead.AtomicRead(Head);
292 NewHead.SetPtr(Item);
293 FLockFreeLinkPolicy::DerefLink(Item)->SingleNext.store(LocalHead.GetPtr(), std::memory_order_relaxed);
295 {
296 break;
297 }
298 }
299 }
300
302 {
303 static_assert(TABAInc > 1, "method should not be used for lists without state");
304 while (true)
305 {
307 LocalHead.AtomicRead(Head);
308 uint64 LocalState = LocalHead.GetState<TABAInc>();
309 TLinkPtr Item = AllocateIfOkToPush(LocalState);
310 if (!Item)
311 {
312 return false;
313 }
314
317 FLockFreeLinkPolicy::DerefLink(Item)->SingleNext.store(LocalHead.GetPtr(), std::memory_order_relaxed);
318 NewHead.SetPtr(Item);
320 {
321 break;
322 }
323 }
324 return true;
325 }
326
327
328 TLinkPtr Pop()
329 {
330 TLinkPtr Item = 0;
331 while (true)
332 {
334 LocalHead.AtomicRead(Head);
335 Item = LocalHead.GetPtr();
336 if (!Item)
337 {
338 break;
339 }
343 NewHead.SetPtr(ItemP->SingleNext.load(std::memory_order_relaxed));
345 {
346 ItemP->SingleNext.store(0, std::memory_order_relaxed);
347 break;
348 }
349 }
350 return Item;
351 }
352
353 TLinkPtr PopAll()
354 {
355 TLinkPtr Item = 0;
356 while (true)
357 {
359 LocalHead.AtomicRead(Head);
360 Item = LocalHead.GetPtr();
361 if (!Item)
362 {
363 break;
364 }
367 NewHead.SetPtr(0);
369 {
370 break;
371 }
372 }
373 return Item;
374 }
375
377 {
378 static_assert(TABAInc > 1, "method should not be used for lists without state");
379 TLinkPtr Item = 0;
380 while (true)
381 {
383 LocalHead.AtomicRead(Head);
384 Item = LocalHead.GetPtr();
387 NewHead.SetState<TABAInc>(StateChange(LocalHead.GetState<TABAInc>()));
388 NewHead.SetPtr(0);
390 {
391 break;
392 }
393 }
394 return Item;
395 }
396
398 {
399 return !Head.GetPtr();
400 }
401
402 [[nodiscard]] inline uint64 GetState() const
403 {
405 LocalHead.AtomicRead(Head);
406 return LocalHead.GetState<TABAInc>();
407 }
408
409private:
410 alignas(TPaddingForCacheContention) TDoublePtr Head;
411};
412
413template<class T, int TPaddingForCacheContention, uint64 TABAInc = 1>
415{
417
420 typedef FLockFreeLinkPolicy::TLinkPtr TLinkPtr;
421
422public:
424
426 {
427 while (Pop()) {};
428 }
429
430 void Reset()
431 {
432 while (Pop()) {};
433 RootList.Reset();
434 }
435
437 {
439 FLockFreeLinkPolicy::DerefLink(Item)->Payload.store(InPayload, std::memory_order_relaxed);
440 RootList.Push(Item);
441 }
442
444 {
445 TLinkPtr Item = 0;
446
447 auto AllocateIfOkToPush = [&OkToPush, InPayload, &Item](uint64 State)->TLinkPtr
448 {
449 if (OkToPush(State))
450 {
451 if (!Item)
452 {
454 FLockFreeLinkPolicy::DerefLink(Item)->Payload.store(InPayload, std::memory_order_relaxed);
455 }
456 return Item;
457 }
458 return 0;
459 };
460 if (!RootList.PushIf(AllocateIfOkToPush))
461 {
462 if (Item)
463 {
464 // we allocated the link, but it turned out that the list was closed
466 }
467 return false;
468 }
469 return true;
470 }
471
472
473 [[nodiscard]] T* Pop()
474 {
475 TLinkPtr Item = RootList.Pop();
476 T* Result = nullptr;
477 if (Item)
478 {
479 Result = (T*)FLockFreeLinkPolicy::DerefLink(Item)->Payload.load(std::memory_order_relaxed);
481 }
482 return Result;
483 }
484
485 template <typename ContainerType>
486 void PopAll(ContainerType& OutContainer)
487 {
488 TLinkPtr Links = RootList.PopAll();
489 while (Links)
490 {
492 OutContainer.Add((T*)LinksP->Payload.load(std::memory_order_relaxed));
493 TLinkPtr Del = Links;
494 Links = LinksP->SingleNext.load(std::memory_order_relaxed);
496 }
497 }
498
499 template <typename FunctorType>
500 void PopAllAndApply(FunctorType InFunctor)
501 {
502 TLinkPtr Links = RootList.PopAll();
503 while (Links)
504 {
506 InFunctor((T*)LinksP->Payload.load(std::memory_order_relaxed));
507 TLinkPtr Del = Links;
508 Links = LinksP->SingleNext.load(std::memory_order_relaxed);
510 }
511 }
512
513 template <typename ContainerType>
514 void PopAllAndChangeState(ContainerType& OutContainer, TFunctionRef<uint64(uint64)> StateChange)
515 {
516 TLinkPtr Links = RootList.PopAllAndChangeState(StateChange);
517 while (Links)
518 {
520 OutContainer.Add((T*)LinksP->Payload.load(std::memory_order_relaxed));
521 TLinkPtr Del = Links;
522 Links = LinksP->SingleNext.load(std::memory_order_relaxed);
524 }
525 }
526
528 {
529 return RootList.IsEmpty();
530 }
531
533 {
534 return RootList.GetState();
535 }
536
537private:
538
540};
541
542template<class T, int TPaddingForCacheContention, uint64 TABAInc = 1>
544{
546
549 typedef FLockFreeLinkPolicy::TLinkPtr TLinkPtr;
550public:
551
553 {
554 // We want to make sure we have quite a lot of extra counter values to avoid the ABA problem. This could probably be relaxed, but eventually it will be dangerous.
555 // The question is "how many queue operations can a thread starve for".
556 static_assert(TABAInc <= 65536, "risk of ABA problem");
557 static_assert((TABAInc & (TABAInc - 1)) == 0, "must be power of two");
558
559 Head.Init();
560 Tail.Init();
562 Head.SetPtr(Stub);
563 Tail.SetPtr(Stub);
564 }
565
567 {
568 while (Pop()) {};
570 }
571
573 {
575 FLockFreeLinkPolicy::DerefLink(Item)->Payload.store(InPayload, std::memory_order_relaxed);
577 while (true)
578 {
579 LocalTail.AtomicRead(Tail);
582 LocalNext.AtomicRead(LocalTailP->DoubleNext);
586 {
587 if (LocalNext.GetPtr())
588 {
592 NewTail.SetPtr(LocalNext.GetPtr());
594 }
595 else
596 {
600 NewNext.SetPtr(Item);
601 if (LocalTailP->DoubleNext.InterlockedCompareExchange(NewNext, LocalNext))
602 {
603 break;
604 }
605 }
606 }
607 }
608 {
612 NewTail.SetPtr(Item);
614 }
615 }
616
617 [[nodiscard]] T* Pop()
618 {
619 T* Result = nullptr;
621 while (true)
622 {
623 LocalHead.AtomicRead(Head);
625 LocalTail.AtomicRead(Tail);
631 {
632 if (LocalHead.GetPtr() == LocalTail.GetPtr())
633 {
634 if (!LocalNext.GetPtr())
635 {
636 return nullptr;
637 }
641 NewTail.SetPtr(LocalNext.GetPtr());
643 }
644 else
645 {
647 Result = (T*)FLockFreeLinkPolicy::DerefLink(LocalNext.GetPtr())->Payload.load(std::memory_order_relaxed);
650 NewHead.SetPtr(LocalNext.GetPtr());
652 {
653 break;
654 }
655 }
656 }
657 }
659 return Result;
660 }
661
662 template <typename ContainerType>
663 void PopAll(ContainerType& OutContainer)
664 {
665 while (T* Item = Pop())
666 {
667 OutContainer.Add(Item);
668 }
669 }
670
671
672 [[nodiscard]] inline bool IsEmpty() const
673 {
675 LocalHead.AtomicRead(Head);
678 return !LocalNext.GetPtr();
679 }
680
681private:
682 alignas(TPaddingForCacheContention) TDoublePtr Head;
683 alignas(TPaddingForCacheContention) TDoublePtr Tail;
684};
685
686
687template<class T, int TPaddingForCacheContention, int NumPriorities>
689{
691
694 typedef FLockFreeLinkPolicy::TLinkPtr TLinkPtr;
695public:
697 {
698 MasterState.Init();
699 }
701 {
704 LocalMasterState.AtomicRead(MasterState);
705 PriorityQueues[Priority].Push(InPayload);
708 int32 ThreadToWake = FindThreadToWake(LocalMasterState.GetPtr());
709 if (ThreadToWake >= 0)
710 {
711 NewMasterState.SetPtr(TurnOffBit(LocalMasterState.GetPtr(), ThreadToWake));
712 }
713 else
714 {
715 NewMasterState.SetPtr(LocalMasterState.GetPtr());
716 }
718 {
719 LocalMasterState.AtomicRead(MasterState);
720 NewMasterState.AdvanceCounterAndState(LocalMasterState, 1);
721 ThreadToWake = FindThreadToWake(LocalMasterState.GetPtr());
722#if 0
723 // This block of code is supposed to avoid starting the task thread if the queues are empty.
724 // There WAS a silly bug here. In rare cases no task thread is woken up.
725 // That bug has been fixed, but I don't think we really need this code anyway.
726 // Without this block, it is possible that we do a redundant wake-up, but for task threads, that can happen anyway.
727 // For named threads, the rare redundant wakeup seems acceptable.
728 if (ThreadToWake >= 0)
729 {
730 bool bAny = false;
731 for (int32 Index = 0; !bAny && Index < NumPriorities; Index++)
732 {
733 bAny = !PriorityQueues[Index].IsEmpty();
734 }
735 if (!bAny) // if there is nothing in the queues, then don't wake anyone
736 {
737 ThreadToWake = -1;
738 }
739 }
740#endif
741 if (ThreadToWake >= 0)
742 {
743 NewMasterState.SetPtr(TurnOffBit(LocalMasterState.GetPtr(), ThreadToWake));
744 }
745 else
746 {
747 NewMasterState.SetPtr(LocalMasterState.GetPtr());
748 }
749 }
750 return ThreadToWake;
751 }
752
754 {
756
757 while (true)
758 {
760 LocalMasterState.AtomicRead(MasterState);
761 //checkLockFreePointerList(!TestBit(LocalMasterState.GetPtr(), MyThread) || !FPlatformProcess::SupportsMultithreading()); // you should not be stalled if you are asking for a task
762 for (int32 Index = 0; Index < NumPriorities; Index++)
763 {
764 T *Result = PriorityQueues[Index].Pop();
765 if (Result)
766 {
767 while (true)
768 {
771 NewMasterState.SetPtr(LocalMasterState.GetPtr());
773 {
774 return Result;
775 }
776 LocalMasterState.AtomicRead(MasterState);
777 checkLockFreePointerList(!TestBit(LocalMasterState.GetPtr(), MyThread) || !FPlatformProcess::SupportsMultithreading()); // you should not be stalled if you are asking for a task
778 }
779 }
780 }
781 if (!bAllowStall)
782 {
783 break; // if we aren't stalling, we are done, the queues are empty
784 }
785 {
788 NewMasterState.SetPtr(TurnOnBit(LocalMasterState.GetPtr(), MyThread));
790 {
791 break;
792 }
793 }
794 }
795 return nullptr;
796 }
797
798private:
799
800 [[nodiscard]] static int32 FindThreadToWake(TLinkPtr Ptr)
801 {
802 int32 Result = -1;
803 UPTRINT Test = UPTRINT(Ptr);
804 if (Test)
805 {
806 Result = 0;
807 while (!(Test & 1))
808 {
809 Test >>= 1;
810 Result++;
811 }
812 }
813 return Result;
814 }
815
816 [[nodiscard]] static TLinkPtr TurnOffBit(TLinkPtr Ptr, int32 BitToTurnOff)
817 {
818 return (TLinkPtr)(UPTRINT(Ptr) & ~(UPTRINT(1) << BitToTurnOff));
819 }
820
821 [[nodiscard]] static TLinkPtr TurnOnBit(TLinkPtr Ptr, int32 BitToTurnOn)
822 {
823 return (TLinkPtr)(UPTRINT(Ptr) | (UPTRINT(1) << BitToTurnOn));
824 }
825
826 [[nodiscard]] static bool TestBit(TLinkPtr Ptr, int32 BitToTest)
827 {
828 return !!(UPTRINT(Ptr) & (UPTRINT(1) << BitToTest));
829 }
830
832 // not a pointer to anything, rather tracks the stall state of all threads servicing this queue.
833 alignas(TPaddingForCacheContention) TDoublePtr MasterState;
834};
835
836
837
838
839template<class T, int TPaddingForCacheContention>
840class TLockFreePointerListLIFOPad : private FLockFreePointerListLIFOBase<T, TPaddingForCacheContention>
841{
842public:
843
853
862
868 template <typename ContainerType>
873
877 template <typename FunctorType>
882
894};
895
896template<class T>
898{
899
900};
901
902template<class T, int TPaddingForCacheContention>
903class TLockFreePointerListUnordered : public TLockFreePointerListLIFOPad<T, TPaddingForCacheContention>
904{
905
906};
907
908template<class T, int TPaddingForCacheContention>
909class TLockFreePointerListFIFO : private FLockFreePointerFIFOBase<T, TPaddingForCacheContention>
910{
911public:
912
922
931
937 template <typename ContainerType>
942
954};
955
956
957template<class T, int TPaddingForCacheContention>
959{
960public:
961
969
977 {
978 return FLockFreePointerListLIFOBase<T, TPaddingForCacheContention, 2>::PushIf(NewItem, [](uint64 State)->bool {return !(State & 1); });
979 }
980
986 template <typename ContainerType>
987 void PopAllAndClose(ContainerType& Output)
988 {
989 auto CheckOpenAndClose = [](uint64 State) -> uint64
990 {
991 checkLockFreePointerList(!(State & 1));
992 return State | 1;
993 };
995 }
996
1006
1007};
1008
1009
constexpr bool IsAligned(T Val, uint64 Alignment)
Definition AlignmentTemplates.h:50
#define check(expr)
Definition AssertionMacros.h:314
#define UE_NONCOPYABLE(TypeName)
Definition CoreMiscDefines.h:457
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
#define MS_ALIGN(n)
Definition Platform.h:916
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
FPlatformTypes::UPTRINT UPTRINT
An unsigned integer the same size as a pointer.
Definition Platform.h:1146
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
#define UNLIKELY(x)
Definition Platform.h:857
#define PLATFORM_CACHE_LINE_SIZE
Definition Platform.h:938
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
CORE_API void * LockFreeAllocLinks(SIZE_T AllocSize)
Definition LockFreeList.cpp:64
UE_FORCEINLINE_HINT uint32 GetPtr() const
Definition LockFreeList.h:15
UE_FORCEINLINE_HINT uint64 GetCounterAndState() const
Definition LockFreeList.h:25
void SetAll(uint32 Ptr, uint64 CounterAndState)
Definition LockFreeList.h:9
CORE_API void LockFreeTagCounterHasOverflowed()
Definition LockFreeList.cpp:41
#define MAX_TagBitsValue
Definition LockFreeList.h:130
#define MAX_LOCK_FREE_LINKS
Definition LockFreeList.h:56
#define MAX_LOCK_FREE_LINKS_AS_BITS
Definition LockFreeList.h:55
UE_FORCEINLINE_HINT void SetCounterAndState(uint64 To)
Definition LockFreeList.h:30
CORE_API void LockFreeLinksExhausted(uint32 TotalNum)
Definition LockFreeList.cpp:47
CORE_API int32 GTestCriticalStalls
Definition LockFreeList.cpp:31
struct FIndexedLockFreeLink GCC_ALIGN
#define checkLockFreePointerList
Definition LockFreeList.h:24
CORE_API void DoTestCriticalStall()
Definition LockFreeList.cpp:18
CORE_API void LockFreeFreeLinks(SIZE_T AllocSize, void *Ptr)
Definition LockFreeList.cpp:69
void TestCriticalStall()
Definition LockFreeList.h:37
#define DECLARE_LOG_CATEGORY_EXTERN(CategoryName, DefaultVerbosity, CompileTimeVerbosity)
Definition LogMacros.h:361
UE_REWRITE constexpr void Exchange(T &A, T &B)
Definition UnrealTemplate.h:627
int BlockIndex
Definition binka_ue_decode_test.cpp:38
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition LockFreeList.h:544
~FLockFreePointerFIFOBase()
Definition LockFreeList.h:566
FLockFreePointerFIFOBase()
Definition LockFreeList.h:552
T * Pop()
Definition LockFreeList.h:617
void Push(T *InPayload)
Definition LockFreeList.h:572
void PopAll(ContainerType &OutContainer)
Definition LockFreeList.h:663
bool IsEmpty() const
Definition LockFreeList.h:672
Definition LockFreeList.h:415
UE_FORCEINLINE_HINT uint64 GetState() const
Definition LockFreeList.h:532
~FLockFreePointerListLIFOBase()
Definition LockFreeList.h:425
bool PushIf(T *InPayload, TFunctionRef< bool(uint64)> OkToPush)
Definition LockFreeList.h:443
T * Pop()
Definition LockFreeList.h:473
UE_FORCEINLINE_HINT bool IsEmpty() const
Definition LockFreeList.h:527
void PopAllAndChangeState(ContainerType &OutContainer, TFunctionRef< uint64(uint64)> StateChange)
Definition LockFreeList.h:514
void Reset()
Definition LockFreeList.h:430
void PopAllAndApply(FunctorType InFunctor)
Definition LockFreeList.h:500
void Push(T *InPayload)
Definition LockFreeList.h:436
void PopAll(ContainerType &OutContainer)
Definition LockFreeList.h:486
Definition LockFreeList.h:262
UE_FORCEINLINE_HINT bool IsEmpty() const
Definition LockFreeList.h:397
TLinkPtr PopAllAndChangeState(TFunctionRef< uint64(uint64)> StateChange)
Definition LockFreeList.h:376
TLinkPtr PopAll()
Definition LockFreeList.h:353
bool PushIf(TFunctionRef< TLinkPtr(uint64)> AllocateIfOkToPush)
Definition LockFreeList.h:301
uint64 GetState() const
Definition LockFreeList.h:402
void Push(TLinkPtr Item)
Definition LockFreeList.h:284
void Reset()
Definition LockFreeList.h:279
TLinkPtr Pop()
Definition LockFreeList.h:328
FLockFreePointerListLIFORoot()
Definition LockFreeList.h:270
Definition LockFreeList.h:689
int32 Push(T *InPayload, uint32 Priority)
Definition LockFreeList.h:700
FStallingTaskQueue()
Definition LockFreeList.h:696
T * Pop(int32 MyThread, bool bAllowStall)
Definition LockFreeList.h:753
Definition ThreadSafeCounter.h:14
int32 Increment()
Definition ThreadSafeCounter.h:52
int32 Add(int32 Amount)
Definition ThreadSafeCounter.h:64
int32 GetValue() const
Definition ThreadSafeCounter.h:120
void PopAllAndClose(ContainerType &Output)
Definition LockFreeList.h:987
void Reset()
Definition LockFreeList.h:965
bool PushIfNotClosed(T *NewItem)
Definition LockFreeList.h:976
bool IsClosed() const
Definition LockFreeList.h:1002
Definition AssetRegistryState.h:50
Definition LockFreeList.h:60
T * GetItem(uint32 Index)
Definition LockFreeList.h:89
uint32 Alloc(uint32 Count=1)
Definition LockFreeList.h:76
TLockFreeAllocOnceIndexedAllocator()
Definition LockFreeList.h:67
Definition LockFreeList.h:910
UE_FORCEINLINE_HINT bool IsEmpty() const
Definition LockFreeList.h:950
T * Pop()
Definition LockFreeList.h:927
void PopAll(ContainerType &Output)
Definition LockFreeList.h:938
void Push(T *NewItem)
Definition LockFreeList.h:918
Definition LockFreeList.h:841
void PopAll(ContainerType &Output)
Definition LockFreeList.h:869
void Push(T *NewItem)
Definition LockFreeList.h:849
void PopAllAndApply(FunctorType InFunctor)
Definition LockFreeList.h:878
T * Pop()
Definition LockFreeList.h:858
UE_FORCEINLINE_HINT bool IsEmpty() const
Definition LockFreeList.h:890
Definition LockFreeList.h:898
Definition LockFreeList.h:904
Definition TestUtils.cpp:8
UE_STRING_CLASS Result(Forward< LhsType >(Lhs), RhsLen)
Definition String.cpp.inl:732
U16 Index
Definition radfft.cpp:71
static CORE_API bool SupportsMultithreading()
Definition GenericPlatformProcess.cpp:656
Definition LockFreeList.h:136
void Init()
Definition LockFreeList.h:141
UE_FORCEINLINE_HINT bool operator==(const FIndexedPointer &Other) const
Definition LockFreeList.h:209
UE_FORCEINLINE_HINT void SetPtr(uint32 To)
Definition LockFreeList.h:157
UE_FORCEINLINE_HINT bool operator!=(const FIndexedPointer &Other) const
Definition LockFreeList.h:213
bool InterlockedCompareExchange(const FIndexedPointer &Exchange, const FIndexedPointer &Comparand)
Definition LockFreeList.h:202
void AdvanceCounterAndState(const FIndexedPointer &From, uint64 TABAInc)
Definition LockFreeList.h:172
UE_FORCEINLINE_HINT void SetCounterAndState(uint64 To)
Definition LockFreeList.h:167
void AtomicRead(const FIndexedPointer &Other)
Definition LockFreeList.h:195
void SetState(uint64 Value)
Definition LockFreeList.h:189
UE_FORCEINLINE_HINT uint64 GetCounterAndState() const
Definition LockFreeList.h:162
UE_FORCEINLINE_HINT uint32 GetPtr() const
Definition LockFreeList.h:152
UE_FORCEINLINE_HINT uint64 GetState() const
Definition LockFreeList.h:183
void SetAll(uint32 Ptr, uint64 CounterAndState)
Definition LockFreeList.h:146
Definition LockFreeList.h:232
static CORE_API uint32 AllocLockFreeLink()
Definition LockFreeList.cpp:264
@ MAX_BITS_IN_TLinkPtr
Definition LockFreeList.h:235
static CORE_API void FreeLockFreeLink(uint32 Item)
Definition LockFreeList.cpp:259
static CORE_API TAllocator LinkAllocator
Definition LockFreeList.h:257
TLockFreeAllocOnceIndexedAllocator< FIndexedLockFreeLink, MAX_LOCK_FREE_LINKS, 16384 > TAllocator
Definition LockFreeList.h:240
static UE_FORCEINLINE_HINT FIndexedLockFreeLink * IndexToLink(uint32 Index)
Definition LockFreeList.h:246
uint32 TLinkPtr
Definition LockFreeList.h:239
FIndexedPointer TDoublePtr
Definition LockFreeList.h:237
FIndexedLockFreeLink TLink
Definition LockFreeList.h:238
static UE_FORCEINLINE_HINT uint32 IndexToPtr(uint32 Index)
Definition LockFreeList.h:250
static UE_FORCEINLINE_HINT FIndexedLockFreeLink * DerefLink(uint32 Ptr)
Definition LockFreeList.h:242