Files
UnrealEngineUWP/Engine/Source/Developer/DerivedDataCache/Public/DerivedDataCacheRecord.h
graeme thornton e7986ac620 [Backout] - CL22808749
[FYI] Steve.Robb
Original CL Desc
-----------------------------------------------------------------
TMap and TSet can now be declared as members with forward-declared key and value parameters.
KeyFuncs::KeyInitType and KeyFuncs::ElementInitType typedefs are no longer used and user-defined KeyFuncs do not need to provide them.  Deprecated placeholders for these typedefs exist though they may not be defined exactly as they were before.  A new KeyType typedef needs to be provided by custom KeyFuncs which don't already inherit from BaseKeyFuncs or TDefaultMapKeyFuncs.
KeyConstPointerType, KeyInitType, ValueInitType and ElementInitType typedefs have been deprecated across TMap, TSet and TSortedMap.  Regular C++ parameter-passing semantics should be used instead (const T& Ref or T Value, depending on T).
Added missing FSetElementId::operator!=().

[FYI] steve.robb
#rb james.hopkin
[FYI] henrik.karlsson
#preflight 635a56c15d49a96f7b31938f

[CL 22850782 by graeme thornton in ue5-main branch]
2022-10-29 02:59:59 -04:00

239 lines
7.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Containers/ContainersFwd.h"
#include "DerivedDataCacheKey.h"
#include "DerivedDataValueId.h"
#include "HAL/Platform.h"
#include "Memory/MemoryFwd.h"
#include "Misc/ScopeExit.h"
#include "Templates/Function.h"
#include "Templates/RefCounting.h"
#include "Templates/UniquePtr.h"
#include "Templates/UnrealTemplate.h"
#define UE_API DERIVEDDATACACHE_API
class FCbObject;
class FCbPackage;
class FCbWriter;
namespace UE::DerivedData { class FCacheRecord; }
namespace UE::DerivedData { class FOptionalCacheRecord; }
namespace UE::DerivedData { class FValue; }
namespace UE::DerivedData { class FValueWithId; }
namespace UE::DerivedData { class IRequestOwner; }
namespace UE::DerivedData { using FOnCacheRecordComplete = TUniqueFunction<void (FCacheRecord&& Record)>; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace UE::DerivedData::Private
{
class ICacheRecordInternal
{
public:
virtual ~ICacheRecordInternal() = default;
virtual const FCacheKey& GetKey() const = 0;
virtual const FCbObject& GetMeta() const = 0;
virtual const FValueWithId& GetValue(const FValueId& Id) const = 0;
virtual TConstArrayView<FValueWithId> GetValues() const = 0;
virtual void AddRef() const = 0;
virtual void Release() const = 0;
};
FCacheRecord CreateCacheRecord(ICacheRecordInternal* Record);
class ICacheRecordBuilderInternal
{
public:
virtual ~ICacheRecordBuilderInternal() = default;
virtual void SetMeta(FCbObject&& Meta) = 0;
virtual void AddValue(const FValueId& Id, const FValue& Value) = 0;
virtual FCacheRecord Build() = 0;
virtual void BuildAsync(IRequestOwner& Owner, FOnCacheRecordComplete&& OnComplete) = 0;
};
} // UE::DerivedData::Private
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace UE::DerivedData
{
/**
* A cache record is a key, an array of values, and metadata.
*
* The key must uniquely correspond to its values. The key must never be reused for other values.
* The metadata does not have this requirement and may be used to persist details that vary, such
* as the time to generate the values or the machine that generated them.
*/
class FCacheRecord
{
public:
/** Returns the key that identifies this record in the cache. */
inline const FCacheKey& GetKey() const { return Record->GetKey(); }
/** Returns the metadata. Null when requested with ECachePolicy::SkipMeta. */
inline const FCbObject& GetMeta() const { return Record->GetMeta(); }
/** Returns the value matching the ID. Null if no match. Data is null if skipped. */
inline const FValueWithId& GetValue(const FValueId& Id) const { return Record->GetValue(Id); }
/** Returns a view of the values ordered by ID. Data is null if skipped. */
inline TConstArrayView<FValueWithId> GetValues() const { return Record->GetValues(); }
/** Save the cache record to a compact binary package. */
UE_API FCbPackage Save() const;
/** Append the cache record to an existing package and writer for e.g. a batch of records. */
UE_API void Save(FCbPackage& Attachments, FCbWriter& Writer) const;
/** Load a cache record from a compact binary package. Null on error. */
UE_API static FOptionalCacheRecord Load(const FCbPackage& Package);
UE_API static FOptionalCacheRecord Load(const FCbPackage& Attachments, const FCbObject& Object);
private:
friend class FOptionalCacheRecord;
friend FCacheRecord Private::CreateCacheRecord(Private::ICacheRecordInternal* Record);
/** Construct a cache record. Use Build() or BuildAsync() on FCacheRecordBuilder. */
inline explicit FCacheRecord(Private::ICacheRecordInternal* InRecord)
: Record(InRecord)
{
}
TRefCountPtr<Private::ICacheRecordInternal> Record;
};
/**
* A cache record builder is used to construct a cache record.
*
* Create using a key that uniquely corresponds to the values for the cache record.
* The metadata may vary between records with the same key.
*
* @see FCacheRecord
*/
class FCacheRecordBuilder
{
public:
/**
* Create a cache record builder from a cache key.
*/
UE_API explicit FCacheRecordBuilder(const FCacheKey& Key);
/**
* Set the metadata for the cache record.
*
* @param Meta The metadata, which is cloned if not owned.
*/
inline void SetMeta(FCbObject&& Meta)
{
return RecordBuilder->SetMeta(MoveTemp(Meta));
}
/**
* Add a value to the cache record.
*
* @param Id An ID for the value that is unique within this cache record.
* @param Buffer The value, which is compressed by the builder, and cloned if not owned.
* @param BlockSize The power-of-two block size to encode raw data in. 0 is default.
*/
UE_API void AddValue(const FValueId& Id, const FCompositeBuffer& Buffer, uint64 BlockSize = 0);
UE_API void AddValue(const FValueId& Id, const FSharedBuffer& Buffer, uint64 BlockSize = 0);
/**
* Add a value to the cache record.
*
* @note The ID for the value must be unique within this cache record.
*/
UE_API void AddValue(const FValueWithId& Value);
/**
* Add a value to the cache record.
*
* @param Id An ID for the value that is unique within this cache record.
*/
inline void AddValue(const FValueId& Id, const FValue& Value)
{
return RecordBuilder->AddValue(Id, Value);
}
/**
* Build a cache record, which makes this builder subsequently unusable.
*
* Prefer BuildAsync() when the values are added from raw buffers, which requires compressing
* those buffers before constructing the cache record.
*/
inline FCacheRecord Build()
{
ON_SCOPE_EXIT { RecordBuilder = nullptr; };
return RecordBuilder->Build();
}
/**
* Build a cache record asynchronously, which makes this builder subsequently unusable.
*
* Prefer Build() when the values are added from compressed buffers as compression is already
* complete and BuildAsync() will complete immediately in that case.
*/
inline void BuildAsync(IRequestOwner& Owner, FOnCacheRecordComplete&& OnComplete)
{
return RecordBuilder.Release()->BuildAsync(Owner, MoveTemp(OnComplete));
}
private:
TUniquePtr<Private::ICacheRecordBuilderInternal> RecordBuilder;
};
/**
* A cache record that can be null.
*
* @see FCacheRecord
*/
class FOptionalCacheRecord : private FCacheRecord
{
public:
inline FOptionalCacheRecord() : FCacheRecord(nullptr) {}
inline FOptionalCacheRecord(FCacheRecord&& InRecord) : FCacheRecord(MoveTemp(InRecord)) {}
inline FOptionalCacheRecord(const FCacheRecord& InRecord) : FCacheRecord(InRecord) {}
inline FOptionalCacheRecord& operator=(FCacheRecord&& InRecord) { FCacheRecord::operator=(MoveTemp(InRecord)); return *this; }
inline FOptionalCacheRecord& operator=(const FCacheRecord& InRecord) { FCacheRecord::operator=(InRecord); return *this; }
/** Returns the cache record. The caller must check for null before using this accessor. */
inline const FCacheRecord& Get() const & { return *this; }
inline FCacheRecord Get() && { return MoveTemp(*this); }
inline bool IsNull() const { return !IsValid(); }
inline bool IsValid() const { return Record.IsValid(); }
inline explicit operator bool() const { return IsValid(); }
inline void Reset() { *this = FOptionalCacheRecord(); }
};
} // UE::DerivedData
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace UE::DerivedData
{
/** An implementation of KeyFuncs to compare FCacheRecord by its FCacheKey. */
struct FCacheRecordKeyFuncs
{
using KeyType = FCacheKey;
using KeyInitType = const FCacheKey&;
using ElementInitType = const FCacheRecord&;
static constexpr bool bAllowDuplicateKeys = false;
static inline KeyInitType GetSetKey(ElementInitType Record) { return Record.GetKey(); }
static inline uint32 GetKeyHash(KeyInitType Key) { return GetTypeHash(Key); }
static inline bool Matches(KeyInitType A, KeyInitType B) { return A == B; }
};
} // UE::DerivedData
#undef UE_API