2021-01-21 01:57:01 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "DerivedDataCacheKey.h"
|
|
|
|
|
|
2021-02-24 11:46:41 -04:00
|
|
|
#include "Containers/Set.h"
|
2021-08-05 22:29:19 -04:00
|
|
|
#include "Containers/StringConv.h"
|
2021-05-31 12:43:42 -04:00
|
|
|
#include "DerivedDataCachePrivate.h"
|
2021-03-11 18:12:08 -04:00
|
|
|
#include "Math/UnrealMathUtility.h"
|
2021-02-24 11:46:41 -04:00
|
|
|
#include "Misc/ScopeRWLock.h"
|
2021-08-06 12:51:28 -04:00
|
|
|
#include "Misc/StringBuilder.h"
|
2022-01-26 12:31:58 -05:00
|
|
|
#include "Serialization/CompactBinaryWriter.h"
|
2021-01-21 01:57:01 -04:00
|
|
|
|
2021-04-19 14:28:07 -04:00
|
|
|
namespace UE::DerivedData::Private
|
2021-03-10 17:33:38 -04:00
|
|
|
{
|
2021-01-21 01:57:01 -04:00
|
|
|
|
2021-08-06 12:51:28 -04:00
|
|
|
template <typename CharType>
|
|
|
|
|
static inline void AssertValidCacheBucketName(TStringView<CharType> Name)
|
|
|
|
|
{
|
|
|
|
|
checkf(IsValidCacheBucketName(Name),
|
|
|
|
|
TEXT("A cache bucket name must be alphanumeric, non-empty, and contain fewer than 256 code units. ")
|
|
|
|
|
TEXT("Name: '%s'"), *WriteToString<256>(Name));
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-19 14:28:07 -04:00
|
|
|
class FCacheBucketOwner : public FCacheBucket
|
|
|
|
|
{
|
|
|
|
|
public:
|
2021-08-06 12:51:28 -04:00
|
|
|
inline explicit FCacheBucketOwner(FAnsiStringView Bucket);
|
2021-04-19 14:28:07 -04:00
|
|
|
inline FCacheBucketOwner(FCacheBucketOwner&& Bucket);
|
|
|
|
|
inline ~FCacheBucketOwner();
|
|
|
|
|
|
|
|
|
|
FCacheBucketOwner(const FCacheBucketOwner&) = delete;
|
|
|
|
|
FCacheBucketOwner& operator=(const FCacheBucketOwner&) = delete;
|
|
|
|
|
|
|
|
|
|
using FCacheBucket::operator==;
|
|
|
|
|
|
2021-08-06 12:51:28 -04:00
|
|
|
inline bool operator==(FAnsiStringView Bucket) const { return ToString().Equals(Bucket, ESearchCase::IgnoreCase); }
|
2021-05-25 11:02:36 -04:00
|
|
|
|
|
|
|
|
friend inline uint32 GetTypeHash(const FCacheBucketOwner& Bucket)
|
|
|
|
|
{
|
2021-08-06 12:51:28 -04:00
|
|
|
return ::GetTypeHash(Bucket.ToString());
|
2021-05-25 11:02:36 -04:00
|
|
|
}
|
2021-04-19 14:28:07 -04:00
|
|
|
};
|
|
|
|
|
|
2021-08-06 12:51:28 -04:00
|
|
|
inline FCacheBucketOwner::FCacheBucketOwner(FAnsiStringView Bucket)
|
2021-04-19 14:28:07 -04:00
|
|
|
{
|
|
|
|
|
const int32 BucketLen = Bucket.Len();
|
2021-08-06 12:51:28 -04:00
|
|
|
const int32 PrefixSize = FMath::DivideAndRoundUp<int32>(1, sizeof(ANSICHAR));
|
|
|
|
|
ANSICHAR* Buffer = new ANSICHAR[PrefixSize + BucketLen + 1];
|
2021-04-19 14:28:07 -04:00
|
|
|
Buffer += PrefixSize;
|
2021-08-06 12:51:28 -04:00
|
|
|
Name = Buffer;
|
2021-04-19 14:28:07 -04:00
|
|
|
|
|
|
|
|
reinterpret_cast<uint8*>(Buffer)[LengthOffset] = static_cast<uint8>(BucketLen);
|
|
|
|
|
Bucket.CopyString(Buffer, BucketLen);
|
|
|
|
|
Buffer += BucketLen;
|
2021-08-06 12:51:28 -04:00
|
|
|
*Buffer = '\0';
|
2021-04-19 14:28:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline FCacheBucketOwner::FCacheBucketOwner(FCacheBucketOwner&& Bucket)
|
|
|
|
|
: FCacheBucket(Bucket)
|
|
|
|
|
{
|
|
|
|
|
Bucket.Reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline FCacheBucketOwner::~FCacheBucketOwner()
|
|
|
|
|
{
|
2021-08-06 12:51:28 -04:00
|
|
|
if (Name)
|
2021-04-19 14:28:07 -04:00
|
|
|
{
|
2021-08-06 12:51:28 -04:00
|
|
|
const int32 PrefixSize = FMath::DivideAndRoundUp<int32>(1, sizeof(ANSICHAR));
|
|
|
|
|
delete[] (Name - PrefixSize);
|
2021-04-19 14:28:07 -04:00
|
|
|
}
|
|
|
|
|
}
|
2021-01-21 01:57:01 -04:00
|
|
|
|
2021-02-24 11:46:41 -04:00
|
|
|
class FCacheBuckets
|
2021-01-21 01:57:01 -04:00
|
|
|
{
|
2021-02-24 11:46:41 -04:00
|
|
|
public:
|
2021-08-06 12:51:28 -04:00
|
|
|
template <typename CharType>
|
|
|
|
|
inline FCacheBucket FindOrAdd(TStringView<CharType> Name);
|
2021-02-24 11:46:41 -04:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
FRWLock Lock;
|
2021-04-19 14:28:07 -04:00
|
|
|
TSet<FCacheBucketOwner> Buckets;
|
2021-02-24 11:46:41 -04:00
|
|
|
};
|
|
|
|
|
|
2021-08-06 12:51:28 -04:00
|
|
|
template <typename CharType>
|
|
|
|
|
inline FCacheBucket FCacheBuckets::FindOrAdd(TStringView<CharType> Name)
|
2021-04-19 14:28:07 -04:00
|
|
|
{
|
2021-08-06 12:51:28 -04:00
|
|
|
const auto AnsiCast = StringCast<ANSICHAR>(Name.GetData(), Name.Len());
|
|
|
|
|
const FAnsiStringView AnsiName = AnsiCast;
|
|
|
|
|
|
|
|
|
|
const uint32 Hash = GetTypeHash(AnsiName);
|
|
|
|
|
if (FReadScopeLock ReadLock(Lock); const FCacheBucketOwner* Bucket = Buckets.FindByHash(Hash, AnsiName))
|
2021-04-19 14:28:07 -04:00
|
|
|
{
|
|
|
|
|
return *Bucket;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-06 12:51:28 -04:00
|
|
|
// It is valid to assert after because the "bogus char" '?' is not valid in a bucket name.
|
2021-05-31 12:43:42 -04:00
|
|
|
AssertValidCacheBucketName(Name);
|
2021-04-19 14:28:07 -04:00
|
|
|
|
2021-08-06 12:51:28 -04:00
|
|
|
FCacheBucketOwner LocalBucket(AnsiName);
|
2021-04-19 14:28:07 -04:00
|
|
|
FWriteScopeLock WriteLock(Lock);
|
|
|
|
|
return Buckets.FindOrAddByHash(Hash, MoveTemp(LocalBucket));
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-06 12:51:28 -04:00
|
|
|
static FCacheBuckets& GetCacheBuckets()
|
2021-02-24 11:46:41 -04:00
|
|
|
{
|
|
|
|
|
static FCacheBuckets Buckets;
|
2021-08-06 12:51:28 -04:00
|
|
|
return Buckets;
|
2021-01-21 01:57:01 -04:00
|
|
|
}
|
|
|
|
|
|
2021-04-19 14:28:07 -04:00
|
|
|
} // UE::DerivedData::Private
|
2021-08-06 12:51:28 -04:00
|
|
|
|
|
|
|
|
namespace UE::DerivedData
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
FCacheBucket::FCacheBucket(FUtf8StringView InName)
|
|
|
|
|
: FCacheBucket(Private::GetCacheBuckets().FindOrAdd(InName))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FCacheBucket::FCacheBucket(FWideStringView InName)
|
|
|
|
|
: FCacheBucket(Private::GetCacheBuckets().FindOrAdd(InName))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-26 12:31:58 -05:00
|
|
|
FCbWriter& operator<<(FCbWriter& Writer, const FCacheKey& Key)
|
|
|
|
|
{
|
|
|
|
|
Writer.BeginObject();
|
|
|
|
|
Writer.AddString("Bucket"_ASV, Key.Bucket.ToString());
|
|
|
|
|
Writer.AddHash("Hash"_ASV, Key.Hash);
|
|
|
|
|
Writer.EndObject();
|
|
|
|
|
return Writer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-06 12:51:28 -04:00
|
|
|
} // UE::DerivedData
|