UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
DiscardableKeyValueCache.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
7
8/*
9Implements a thread-safe discardable Key/Value cache by using two maps - a primary and a backfill.
10
11Find() checks the current map first then the backfill. Entries found in the backfill are moved into
12the primary map.
13
14When Swap is called all items in the backfill are removed and the currentmap & backfill are swapped.
15
16This results in most recently used items being retained and older/unused items being evicted. The more often Swap
17is called the shorter the lifespan for items
18*/
19template<class KeyType, class ValueType>
21{
22public:
23
24 /* Flags used when calling Find() */
25 struct LockFlags
26 {
27 enum Flags
28 {
29 ReadLock = (1 << 0),
30 WriteLock = (1 << 1),
32 };
33 };
34
36
42
43 /* Access to the internal locking object */
45 {
46 return LockObject;
47 }
48
49 /* Reference to the current map */
51 {
52 return *CurrentMap;
53 }
54
55 /* Reference to the current map */
57 {
58 return *BackfillMap;
59 }
60
61 /* Returns the total number of items in the cache*/
63 {
65
66 int32 Count = Map1.Num() + Map2.Num();
67
69
70 return Count;
71 }
72
76 [[nodiscard]] bool Find(const KeyType& Key, ValueType& OutType)
77 {
79
81
83 return Found;
84 }
85
92 [[nodiscard]] bool Find(const KeyType& Key, ValueType& OutType, uint32 InCurrentLockFlags, uint32& OutLockFlags)
93 {
95 }
96
101 bool Add(const KeyType& Key, const ValueType& Value)
102 {
104 bool Success = Add(Key, Value, LockFlags);
106 return Success;
107 }
108
113 bool Add(const KeyType& Key, const ValueType& Value, const uint32 LockFlags)
114 {
115 bool Success = true;
116
117 checkf((LockFlags & LockFlags::WriteLock) != 0, TEXT("Cache is not locked for write during Add!"));
118
119 // key is already here! likely another thread may have filled the cache. calling code should handle this
120 // or request that a write lock be left after a Find() fails.
121 if (CurrentMap->Contains(Key) == false)
122 {
123 CurrentMap->Add(Key, Value);
124 }
125 else
126 {
127 Success = false;
128 }
129
130 return Success;
131 }
132
133 /*
134 Discard all items left in the backfill and swap the current & backfill pointers
135 */
137 {
139
140 int32 Discarded = Discard(LockFlags, LockFlags, [](ValueType& Type) {});
141
143
144 return Discarded;
145 }
146
147 template<typename DeleteFunc>
149 {
151
153
155
156 return Discarded;
157 }
158
162 template<typename DeleteFunc>
164 {
166 {
168 }
169
170 for (auto& KV : *BackfillMap)
171 {
172 Func(KV.Value);
173 }
174
175 int32 Discarded = BackfillMap->Num();
176
177 // free anything still in the backfill map
178 BackfillMap->Empty();
179
180 if (CurrentMap == &Map1)
181 {
182 CurrentMap = &Map2;
183 BackfillMap = &Map1;
184 }
185 else
186 {
187 CurrentMap = &Map1;
188 BackfillMap = &Map2;
189 }
190
192 return Discarded;
193 }
194
195public:
197 {
200
203
204
205 // if already locked for write, nothing to do
207 {
209 }
210
211 // if locked for reads and that's all that's needed, d
213 {
214 return LockFlags::ReadLock;
215 }
216
218
219 // chance they asked for both Read/Write, so check this first
221 {
223 }
224 else if (WantLockForRead)
225 {
227 }
228
229 return NewFlags;
230 }
231
233 {
236
237 if (LockedForWrite)
238 {
240 }
241 else if (LockedForRead)
242 {
244 }
245 }
246
247protected:
248
254 {
255 // by default we'll do exactly what was asked...
256
259
261
264 TEXT("Cache is not locked for read or write during Find!"));
265
266 // Do we have this?
267 ValueType* Found = CurrentMap->Find(Key);
268
269 // If not check the backfill, if it's there remove it add it to our map.
270 if (!Found)
271 {
272 ValueType* BackfillFound = BackfillMap->Find(Key);
273
274 // we either need to lock to adjust our cache, or lock because the user wants to...
276
277 if (NeedWriteLock)
278 {
279 // lock the buffer (nop if we were already locked!)
281
282 // check again, there's a chance these may have changed filled between the unlock/lock
283 // above..
284 Found = CurrentMap->Find(Key);
285 if (!Found)
286 {
287 BackfillFound = BackfillMap->Find(Key);
288 }
289 }
290
291 // If we found a backfill, move it to the primary
292 if (!Found && BackfillFound)
293 {
294 // if shared refs, add/remove order is important
295 Found = &CurrentMap->Add(Key, *BackfillFound);
296 BackfillMap->Remove(Key);
297 }
298 }
299
300 if (Found)
301 {
302 OutType = *Found;
303 }
304
306 return Found != nullptr;
307 }
308
309
315};
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition DiscardableKeyValueCache.h:21
uint32 ApplyLock(uint32 CurrentFlags, uint32 NewFlags)
Definition DiscardableKeyValueCache.h:196
TypedMap Map2
Definition DiscardableKeyValueCache.h:314
FRWLock & RWLock()
Definition DiscardableKeyValueCache.h:44
TypedMap & Current()
Definition DiscardableKeyValueCache.h:50
FRWLock LockObject
Definition DiscardableKeyValueCache.h:310
void Unlock(uint32 Flags)
Definition DiscardableKeyValueCache.h:232
TMap< KeyType, ValueType > TypedMap
Definition DiscardableKeyValueCache.h:35
bool Find(const KeyType &Key, ValueType &OutType)
Definition DiscardableKeyValueCache.h:76
bool Find(const KeyType &Key, ValueType &OutType, uint32 InCurrentLockFlags, uint32 &OutLockFlags)
Definition DiscardableKeyValueCache.h:92
int32 Num()
Definition DiscardableKeyValueCache.h:62
TypedMap Map1
Definition DiscardableKeyValueCache.h:313
bool Add(const KeyType &Key, const ValueType &Value, const uint32 LockFlags)
Definition DiscardableKeyValueCache.h:113
TDiscardableKeyValueCache()
Definition DiscardableKeyValueCache.h:37
int32 Discard(uint32 InCurrentLockFlags, uint32 &OutNewLockFlags, DeleteFunc Func)
Definition DiscardableKeyValueCache.h:163
bool InternalFindWhileLocked(const KeyType &Key, ValueType &OutType, uint32 InCurrentLockFlags, uint32 &OutFlags)
Definition DiscardableKeyValueCache.h:253
bool Add(const KeyType &Key, const ValueType &Value)
Definition DiscardableKeyValueCache.h:101
TypedMap * CurrentMap
Definition DiscardableKeyValueCache.h:311
int32 Discard(DeleteFunc Func)
Definition DiscardableKeyValueCache.h:148
TypedMap & Backfill()
Definition DiscardableKeyValueCache.h:56
TypedMap * BackfillMap
Definition DiscardableKeyValueCache.h:312
int32 Discard()
Definition DiscardableKeyValueCache.h:136
Definition UnrealString.h.inl:34
Definition CriticalSection.h:14
UE_REWRITE void WriteLock()
Definition CriticalSection.h:21
UE_REWRITE void ReadUnlock()
Definition CriticalSection.h:41
UE_REWRITE void WriteUnlock()
Definition CriticalSection.h:26
UE_REWRITE void ReadLock()
Definition CriticalSection.h:36
Definition DiscardableKeyValueCache.h:26
Flags
Definition DiscardableKeyValueCache.h:28
@ WriteLockOnAddFail
Definition DiscardableKeyValueCache.h:31
@ ReadLock
Definition DiscardableKeyValueCache.h:29
@ WriteLock
Definition DiscardableKeyValueCache.h:30