admin管理员组文章数量:1405628
I'm reading the sourece code of GC in Unreal Engine. Here is the implemetaion for the global gc lock:
/**
* Garbage Collection synchronization objects
* Will not lock other threads if GC is not running.
* Has the ability to only lock for GC if no other locks are present.
*/
class FGCCSyncObject
{
/** Non zero if any of the non-game threads is blocking GC */
FThreadSafeCounter AsyncCounter;
/** Non zero if GC is running */
FThreadSafeCounter GCCounter;
/** Non zero if GC wants to run but is blocked by some other thread \
This flag is not automatically enforced on the async threads, instead
threads have to manually implement support for it. */
TAtomic<int32> GCWantsToRunCounter {0};
/** Critical section for thread safe operations */
FCriticalSection Critical;
/** Event used to block non-game threads when GC is running */
FEvent* GCUnlockedEvent;
public:
FGCCSyncObject();
~FGCCSyncObject();
/** Creates the singleton object */
static void Create();
/** Gets the singleton object */
static FGCCSyncObject& Get();
/** Lock on non-game thread. Will block if GC is running. */
void LockAsync()
{
if (!IsInGameThread())
{
// Wait until GC is done if it was running when entering this function
bool bLocked = false;
do
{
if (GCCounter.GetValue() > 0)
{
GCUnlockedEvent->Wait();
}
{
FScopeLock CriticalLock(&Critical);
if (GCCounter.GetValue() == 0)
{
AsyncCounter.Increment();
bLocked = true;
}
}
} while (!bLocked);
}
}
/** Release lock from non-game thread */
void UnlockAsync()
{
if (!IsInGameThread())
{
AsyncCounter.Decrement();
}
}
/** Lock for GC. Will block if any other thread has locked. */
void GCLock()
{
// Signal other threads that GC wants to run
SetGCIsWaiting();
// Wait until all other threads are done if they're currently holding the lock
bool bLocked = false;
do
{
FPlatformProcess::ConditionalSleep([&]()
{
return AsyncCounter.GetValue() == 0;
});
{
FScopeLock CriticalLock(&Critical);
if (AsyncCounter.GetValue() == 0)
{
GCUnlockedEvent->Reset();
int32 GCCounterValue = GCCounter.Increment();
check(GCCounterValue == 1); // GCLock doesn't support recursive locks
// At this point GC can run so remove the signal that it's waiting
FPlatformMisc::MemoryBarrier();
ResetGCIsWaiting();
bLocked = true;
}
}
} while (!bLocked);
}
/** Checks if any async thread has a lock */
bool IsAsyncLocked() const
{
return AsyncCounter.GetValue() != 0;
}
/** Checks if GC has a lock */
bool IsGCLocked() const
{
return GCCounter.GetValue() != 0;
}
/** Lock for GC. Will not block and return false if any other thread has already locked. */
bool TryGCLock()
{
bool bSuccess = false;
FScopeLock CriticalLock(&Critical);
// If any other thread is currently locking we just exit
if (AsyncCounter.GetValue() == 0)
{
GCUnlockedEvent->Reset();
int32 GCCounterValue = GCCounter.Increment();
check(GCCounterValue == 1); // GCLock doesn't support recursive locks
bSuccess = true;
}
return bSuccess;
}
/** Unlock GC */
void GCUnlock()
{
GCUnlockedEvent->Trigger();
GCCounter.Decrement();
}
/** Manually mark GC state as 'waiting to run' */
void SetGCIsWaiting()
{
GCWantsToRunCounter++;
}
/** Manually reset GC 'waiting to run' state*/
void ResetGCIsWaiting()
{
GCWantsToRunCounter.Store(0);
}
/** True if GC wants to run on the game thread but is maybe blocked by some other thread */
FORCEINLINE bool IsGCWaiting() const
{
return !!GCWantsToRunCounter.Load(EMemoryOrder::Relaxed);
}
};
There is a FPlatformMisc::MemoryBarrier()
statement in the GCLock
function. It calls _mm_sfence
in Windows and calls __sync_synchronize
in Unix.
I could not understand why this memory barrier is needed here. What is the purpose of adding it here? What would happen if we remove this statement?
本文标签:
版权声明:本文标题:c++ - What is the purpose of the full memory barrier between two seq_cst operations in FGCCSyncObject::GCLock of Unreal Engine - 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744897898a2631174.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论