UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
GCScopeLock.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3/*=============================================================================
4 Garbage Collection scope lock.
5=============================================================================*/
6
7#pragma once
8
9#include "CoreMinimal.h"
11#include "HAL/PlatformProcess.h"
12#include "Misc/ScopeLock.h"
13#include "HAL/ThreadSafeBool.h"
14#include "Async/SharedMutex.h"
15#include "Async/SharedLock.h"
16#include "Async/UniqueLock.h"
17#include "HAL/Event.h"
18
19
26{
28 FThreadSafeCounter AsyncCounter;
30 FThreadSafeCounter GCCounter;
34 TAtomic<int32> GCWantsToRunCounter {0};
36 UE::FSharedMutex SharedMutex;
38 FEvent* GCUnlockedEvent;
39
40public:
41
44
46 static void Create();
47
49 static FGCCSyncObject& Get();
50
52 void LockAsync()
53 {
54 if (!IsInGameThread())
55 {
56 // Wait until GC is done if it was running when entering this function
57 bool bLocked = false;
58 do
59 {
60 if (GCCounter.GetValue() > 0)
61 {
62 GCUnlockedEvent->Wait();
63 }
64 {
65 // We only need a read lock here since AsyncCounter is already thread-safe
66 // with other threads that want to lock but we need to guard against
67 // the GC trying to take the write lock.
68 UE::TSharedLock SharedLock(SharedMutex);
69 if (GCCounter.GetValue() == 0)
70 {
71 AsyncCounter.Increment();
72 bLocked = true;
73 }
74 }
75 } while (!bLocked);
76 }
77 }
78
80 bool TryLockAsync(bool bShouldLock = !IsInGameThread())
81 {
82 bool bLocked = true;
83 if (bShouldLock)
84 {
85 bLocked = false;
86 if (GCCounter.GetValue() == 0)
87 {
88 UE::TSharedLock SharedLock(SharedMutex);
89 if (GCCounter.GetValue() == 0)
90 {
91 AsyncCounter.Increment();
92 bLocked = true;
93 }
94 }
95 }
96
97 return bLocked;
98 }
99
102 {
103 if (bShouldUnlock)
104 {
105 AsyncCounter.Decrement();
106 }
107 }
109 void GCLock()
110 {
111 // Signal other threads that GC wants to run
113
114 // Wait until all other threads are done if they're currently holding the lock
115 bool bLocked = false;
116 do
117 {
119 {
120 return AsyncCounter.GetValue() == 0;
121 });
122 {
123 // Guard against any reader locks owned by other threads.
124 UE::TUniqueLock ExclusiveLock(SharedMutex);
125 if (AsyncCounter.GetValue() == 0)
126 {
127 GCUnlockedEvent->Reset();
128 int32 GCCounterValue = GCCounter.Increment();
129 check(GCCounterValue == 1); // GCLock doesn't support recursive locks
130 // At this point GC can run so remove the signal that it's waiting
133 bLocked = true;
134 }
135 }
136 } while (!bLocked);
137 }
139 bool IsAsyncLocked() const
140 {
141 return AsyncCounter.GetValue() != 0;
142 }
144 bool IsGCLocked() const
145 {
146 return GCCounter.GetValue() != 0;
147 }
150 {
151 bool bSuccess = false;
152 if (AsyncCounter.GetValue() != 0)
153 {
154 return bSuccess;
155 }
156 // Guard against any reader locks owned by other threads.
157 UE::TUniqueLock ExclusiveLock(SharedMutex);
158 // If any other thread is currently locking we just exit
159 if (AsyncCounter.GetValue() == 0)
160 {
161 GCUnlockedEvent->Reset();
162 int32 GCCounterValue = GCCounter.Increment();
163 check(GCCounterValue == 1); // GCLock doesn't support recursive locks
164 bSuccess = true;
165 }
166 return bSuccess;
167 }
169 void GCUnlock()
170 {
171 GCUnlockedEvent->Trigger();
172 GCCounter.Decrement();
173 }
174
177 {
178 GCWantsToRunCounter++;
179 }
180
183 {
184 GCWantsToRunCounter.Store(0);
185 }
186
189 {
190 return !!GCWantsToRunCounter.Load(EMemoryOrder::Relaxed);
191 }
192};
#define FORCEINLINE
Definition AndroidPlatform.h:140
#define check(expr)
Definition AssertionMacros.h:314
bool bSuccess
Definition ConvexDecomposition3.cpp:819
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
CORE_API bool IsInGameThread()
Definition ThreadingBase.cpp:185
Definition Event.h:21
virtual bool Wait(uint32 WaitTime, const bool bIgnoreThreadIdleStats=false)=0
virtual void Trigger()=0
virtual void Reset()=0
Definition GCScopeLock.h:26
void ResetGCIsWaiting()
Definition GCScopeLock.h:182
bool TryLockAsync(bool bShouldLock=!IsInGameThread())
Definition GCScopeLock.h:80
void GCLock()
Definition GCScopeLock.h:109
bool IsAsyncLocked() const
Definition GCScopeLock.h:139
void GCUnlock()
Definition GCScopeLock.h:169
FGCCSyncObject()
Definition GarbageCollection.cpp:159
static FGCCSyncObject & Get()
Definition GarbageCollection.cpp:185
static void Create()
Definition GarbageCollection.cpp:173
bool TryGCLock()
Definition GCScopeLock.h:149
FORCEINLINE bool IsGCWaiting() const
Definition GCScopeLock.h:188
void UnlockAsync(bool bShouldUnlock=!IsInGameThread())
Definition GCScopeLock.h:101
void LockAsync()
Definition GCScopeLock.h:52
void SetGCIsWaiting()
Definition GCScopeLock.h:176
~FGCCSyncObject()
Definition GarbageCollection.cpp:164
bool IsGCLocked() const
Definition GCScopeLock.h:144
Definition ThreadSafeCounter.h:14
int32 Increment()
Definition ThreadSafeCounter.h:52
int32 Decrement()
Definition ThreadSafeCounter.h:75
int32 GetValue() const
Definition ThreadSafeCounter.h:120
Definition Atomic.h:538
Definition SharedMutex.h:22
Definition SharedLock.h:22
Definition UniqueLock.h:20
static UE_FORCEINLINE_HINT void MemoryBarrier()
Definition AndroidPlatformMisc.h:249
static CORE_API void ConditionalSleep(TFunctionRef< bool()> Condition, float SleepTime=0.0f)
Definition GenericPlatformProcess.cpp:443