Files
UnrealEngineUWP/Engine/Source/Developer/DerivedDataCache/Private/DerivedDataBuildFunctionRegistry.cpp
devin doucette c3443800ec DDC: Converted modular feature names to constant lazy names
#rb Zousar.Shaker
#rnx
#preflight 61f97050fa6554dff3d6fa76

#ROBOMERGE-AUTHOR: devin.doucette
#ROBOMERGE-SOURCE: CL 18812871 in //UE5/Release-5.0/... via CL 18812927 via CL 18822743
#ROBOMERGE-BOT: UE5 (Release-Engine-Test -> Main) (v909-18823584)

[CL 18823987 by devin doucette in ue5-main branch]
2022-02-02 06:26:22 -05:00

156 lines
5.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "DerivedDataBuildFunctionRegistry.h"
#include "Containers/Map.h"
#include "DerivedDataBuildFunction.h"
#include "DerivedDataBuildFunctionFactory.h"
#include "DerivedDataBuildPrivate.h"
#include "DerivedDataSharedString.h"
#include "Features/IModularFeatures.h"
#include "HAL/CriticalSection.h"
#include "Misc/AsciiSet.h"
#include "Misc/Guid.h"
#include "Misc/ScopeRWLock.h"
#include "Misc/StringBuilder.h"
namespace UE::DerivedData::Private
{
class FBuildFunctionRegistry : public IBuildFunctionRegistry
{
public:
FBuildFunctionRegistry();
~FBuildFunctionRegistry();
const IBuildFunction* FindFunction(FUtf8StringView Function) const;
FGuid FindFunctionVersion(FUtf8StringView Function) const;
void IterateFunctionVersions(TFunctionRef<void(FUtf8StringView Function, const FGuid& Version)> Visitor) const;
private:
void OnModularFeatureRegistered(const FName& Type, IModularFeature* ModularFeature);
void OnModularFeatureUnregistered(const FName& Type, IModularFeature* ModularFeature);
void AddFunctionNoLock(IBuildFunctionFactory* Factory);
void RemoveFunction(IBuildFunctionFactory* Factory);
private:
mutable FRWLock Lock;
TMap<FUtf8SharedString, IBuildFunctionFactory*> Functions;
};
FBuildFunctionRegistry::FBuildFunctionRegistry()
{
IModularFeatures& ModularFeatures = IModularFeatures::Get();
for (IBuildFunctionFactory* Factory : ModularFeatures.GetModularFeatureImplementations<IBuildFunctionFactory>(IBuildFunctionFactory::FeatureName))
{
AddFunctionNoLock(Factory);
}
ModularFeatures.OnModularFeatureRegistered().AddRaw(this, &FBuildFunctionRegistry::OnModularFeatureRegistered);
ModularFeatures.OnModularFeatureUnregistered().AddRaw(this, &FBuildFunctionRegistry::OnModularFeatureUnregistered);
}
FBuildFunctionRegistry::~FBuildFunctionRegistry()
{
IModularFeatures& ModularFeatures = IModularFeatures::Get();
ModularFeatures.OnModularFeatureUnregistered().RemoveAll(this);
ModularFeatures.OnModularFeatureRegistered().RemoveAll(this);
}
void FBuildFunctionRegistry::OnModularFeatureRegistered(const FName& Type, IModularFeature* ModularFeature)
{
if (Type == IBuildFunctionFactory::FeatureName)
{
FWriteScopeLock WriteLock(Lock);
AddFunctionNoLock(static_cast<IBuildFunctionFactory*>(ModularFeature));
}
}
void FBuildFunctionRegistry::OnModularFeatureUnregistered(const FName& Type, IModularFeature* ModularFeature)
{
if (Type == IBuildFunctionFactory::FeatureName)
{
RemoveFunction(static_cast<IBuildFunctionFactory*>(ModularFeature));
}
}
void FBuildFunctionRegistry::AddFunctionNoLock(IBuildFunctionFactory* Factory)
{
const IBuildFunction& Function = Factory->GetFunction();
const FUtf8SharedString& FunctionName = Function.GetName();
const uint32 FunctionHash = GetTypeHash(FunctionName);
UE_CLOG(!Function.GetVersion().IsValid(), LogDerivedDataBuild, Error,
TEXT("Version of zero is not allowed in build function with the name %s."), *WriteToString<32>(FunctionName));
UE_CLOG(Functions.FindByHash(FunctionHash, FunctionName), LogDerivedDataBuild, Error,
TEXT("More than one build function has been registered with the name %s."), *WriteToString<32>(FunctionName));
Functions.EmplaceByHash(FunctionHash, FunctionName, Factory);
}
void FBuildFunctionRegistry::RemoveFunction(IBuildFunctionFactory* Factory)
{
const FUtf8SharedString& Function = Factory->GetFunction().GetName();
const uint32 FunctionHash = GetTypeHash(Function);
FWriteScopeLock WriteLock(Lock);
Functions.RemoveByHash(FunctionHash, Function);
}
const IBuildFunction* FBuildFunctionRegistry::FindFunction(FUtf8StringView Function) const
{
const uint32 FunctionHash = GetTypeHash(Function);
FReadScopeLock ReadLock(Lock);
if (IBuildFunctionFactory* const* Factory = Functions.FindByHash(FunctionHash, Function))
{
return &(**Factory).GetFunction();
}
return nullptr;
}
FGuid FBuildFunctionRegistry::FindFunctionVersion(FUtf8StringView Function) const
{
const uint32 FunctionHash = GetTypeHash(Function);
FReadScopeLock ReadLock(Lock);
if (IBuildFunctionFactory* const* Factory = Functions.FindByHash(FunctionHash, Function))
{
return (**Factory).GetFunction().GetVersion();
}
return FGuid();
}
void FBuildFunctionRegistry::IterateFunctionVersions(TFunctionRef<void(FUtf8StringView Function, const FGuid& Version)> Visitor) const
{
TArray<TPair<FUtf8SharedString, FGuid>> FunctionVersions;
{
FReadScopeLock ReadLock(Lock);
FunctionVersions.Reserve(Functions.Num());
for (const TPair<FUtf8SharedString, IBuildFunctionFactory*>& Function : Functions)
{
FunctionVersions.Emplace(Function.Key, Function.Value->GetFunction().GetVersion());
}
}
for (const TPair<FUtf8SharedString, FGuid>& Function : FunctionVersions)
{
Visitor(Function.Key, Function.Value);
}
}
IBuildFunctionRegistry* CreateBuildFunctionRegistry()
{
return new FBuildFunctionRegistry();
}
bool IsValidBuildFunctionName(FUtf8StringView Function)
{
constexpr FAsciiSet Valid("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
return !Function.IsEmpty() && FAsciiSet::HasOnly(Function, Valid);
}
void AssertValidBuildFunctionName(FUtf8StringView Function, FStringView Name)
{
checkf(IsValidBuildFunctionName(Function),
TEXT("A build function name must be alphanumeric and non-empty for build of '%.*s' by '%.*s'."),
Name.Len(), Name.GetData(), *WriteToString<32>(Function));
}
} // UE::DerivedData::Private