Files
UnrealEngine/Engine/Source/Runtime/MassEntity/Private/MassRequirementAccessDetector.cpp
2025-05-18 13:04:45 +08:00

83 lines
2.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MassRequirementAccessDetector.h"
#if WITH_MASSENTITY_DEBUG
#include "MassEntityQuery.h"
#include "HAL/IConsoleManager.h"
#include "MassEntityManager.h"
namespace UE::Mass::Private
{
bool bTrackRequirementsAccess = false;
FAutoConsoleVariableRef CVarTrackRequirementsAccess(TEXT("mass.debug.TrackRequirementsAccess"), bTrackRequirementsAccess
, TEXT("Enables Mass processing debugging mode where we monitor thread-safety of query requirements access."));
}
void FMassRequirementAccessDetector::Initialize()
{
check(IsInGameThread());
AddDetectors(FMassFragmentBitSet::FStructTrackerWrapper::StructTracker);
AddDetectors(FMassChunkFragmentBitSet::FStructTrackerWrapper::StructTracker);
AddDetectors(FMassSharedFragmentBitSet::FStructTrackerWrapper::StructTracker);
AddDetectors(FMassExternalSubsystemBitSet::FStructTrackerWrapper::StructTracker);
}
void FMassRequirementAccessDetector::AddDetectors(const FStructTracker& StructTracker)
{
TConstArrayView<TWeakObjectPtr<const UStruct>> Types = StructTracker.DebugGetAllStructTypes<UStruct>();
for (TWeakObjectPtr<const UStruct> Type : Types)
{
check(Type.Get());
Detectors.Add(Type.Get(), MakeShareable(new FRWAccessDetector()));
}
}
void FMassRequirementAccessDetector::RequireAccess(const FMassEntityQuery& Query)
{
if (UE::Mass::Private::bTrackRequirementsAccess)
{
Operation(Query.RequiredConstSubsystems, &FRWAccessDetector::AcquireReadAccess);
Operation(Query.RequiredMutableSubsystems, &FRWAccessDetector::AcquireWriteAccess);
Aquire(Query.FragmentRequirements);
Aquire(Query.ChunkFragmentRequirements);
Aquire(Query.ConstSharedFragmentRequirements);
Aquire(Query.SharedFragmentRequirements);
}
}
void FMassRequirementAccessDetector::ReleaseAccess(const FMassEntityQuery& Query)
{
if (UE::Mass::Private::bTrackRequirementsAccess)
{
Operation(Query.RequiredConstSubsystems, &FRWAccessDetector::ReleaseReadAccess);
Operation(Query.RequiredMutableSubsystems, &FRWAccessDetector::ReleaseWriteAccess);
Release(Query.FragmentRequirements);
Release(Query.ChunkFragmentRequirements);
Release(Query.ConstSharedFragmentRequirements);
Release(Query.SharedFragmentRequirements);
}
}
namespace UE::Mass::Debug
{
//-----------------------------------------------------------------------------
// FScopedRequirementAccessDetector
//-----------------------------------------------------------------------------
FScopedRequirementAccessDetector::FScopedRequirementAccessDetector(const FMassEntityQuery& InQuery)
: EntityManager(InQuery.GetEntityManager())
, Query(InQuery)
{
EntityManager->GetRequirementAccessDetector().RequireAccess(InQuery);
}
FScopedRequirementAccessDetector::~FScopedRequirementAccessDetector()
{
EntityManager->GetRequirementAccessDetector().ReleaseAccess(Query);
}
}
#endif // WITH_MASSENTITY_DEBUG