ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
lrucachetable.inl
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_containers of the \aliblong.
4///
5/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace containers {
9
10/// This type implements a container used for caching objects. When its #Size reaches its #Capacity,
11/// one of the least recently used (LRU) objects is replaced with the next insertion of a non-cached
12/// object.
13///
14/// This implementation uses an array of lists. The lists are forward lists of cached elements
15/// sorted by their insertion time, with the latest insertion in the front.
16/// The list (within the array of lists) used to store and later search an object, is chosen by
17/// the hash value of its key, modulo the number of lists in place.
18/// Both, the size of the lists as well the number of lists (the size of the array) can be chosen
19/// on construction or with method #Reserve.
20/// The memory needed for all entries (and the array of pointers to the start of the list)
21/// is allocated once, when the capacity is set. Generic allocation options (heap-, monotonic-
22/// and pool allocation) are given with template parameter \p{TAllocator}.<br>
23/// Together with the custom data, the data's key's hashcode is stored with each element.
24/// This can reduce search time dramatically in some cases, because the equal functor is invoked
25/// only if two objects have the same hashcode.
26///
27/// This design has the following consequences:
28/// - The maximum amount of objects stored, equals the product of the size of the hash-array
29/// and the maximum size of the list.
30/// - The maximum number of comparisons performed before a cache miss is detected, equals
31/// the maximum size of the lists.
32/// - The \b last recently used object is always found with only one comparison. The probability
33/// that other previously used objects (the second last, third last, etc) are likewise found
34/// with only one comparison, rises with the size of the array of lists.
35/// - This container does not necessarily free the least recently used object with the insertion
36/// of an unknown one. Instead, the least recently used object of those cached objects whose hash
37/// function leads to the same list index is freed.
38///
39/// As a sample, two reasonable use cases taken from \alib should be quickly discussed:
40/// 1. Class \alib{files;OwnerAndGroupResolver} of camp \alib_files:
41/// - The type translates owner and group IDs of files to corresponding owner and group names.
42/// - For this, the OS has to be called.
43/// - If, for example, a directory listing similar to bash command <c>ls -la</c> is to be printed,
44/// the entries in a directory usually share the same owner with very few exceptions.
45/// This is true for home directories inside <c>/home</c> as well as for system directories
46/// like <c>/usr/bin</c>.
47/// - A perfect exception is directory <c>/home</c> itself. Here, every subfolder belongs to a
48/// different owner.
49///
50/// This sample shows that already a very small cache capacity can dramatically decrease the
51/// number of calls to the OS. On the other hand, in the case of the exceptional folders, still
52/// the number of searches performed before a cache-miss is detected is limited to the length
53/// of the lists and not to the total capacity.
54/// The default capacity of the \b %LRUCacheTable chosen by class \b OwnerAndGroupResolver is
55/// <c>6 x 6</c> and can be changed with
56/// \alib{files::OwnerAndGroupResolver;SetOwnerCacheCapacity} and
57/// \alib{files::OwnerAndGroupResolver;SetGroupCacheCapacity}.
58/// 2. Camp \alib_alox:
59/// - With each log operation the placement of the call in a sourcefile (\alib{lox;Scope})
60/// is evaluated to resolve the resulting
61/// \"\ref alib_mod_alox_tak_terminology_domains "Log Domain"\".
62/// - For this, the source file name given by the C++ preprocessor, is to be parsed.
63/// - \alox uses an \b %LRUCacheTable to avoid parsing repetitive scopes.
64/// - It is very much depending on the use case of logging, how often repetitive scopes occur.
65/// For example, if verbose logging is active, series of log statements comming from the same
66/// code entity should be expected. If logging is limited and furthermore logging is made
67/// in parallel by multiple threads, then the scopes should be rather mixed, but still
68/// resulting from a limited number of files during a certain period of execution time.
69///
70/// The default capacity of the \b %LRUCacheTable chosen by \alib is likewise <c>4 x 6</c>
71/// and can be changed with \alib{lox;Lox::SetFileNameCacheCapacity}.
72///
73/// Choosing the right values for the two dimensions of the capacity, depends on different
74/// factors of the specific use case, and in most cases cannot be chosen to be perfect in
75/// all situations. Among the things to consider are:
76/// - The costs of creating a new object.
77/// - The cost of comparing two keys.
78/// - The statistical distribution of requests on (later) objects. In cases of even
79/// distribution, the use of this type can become counter-productive!
80/// - Potential memory constraints of the target platform, which may limit the capacity to set.
81///
82/// The stored type is not restricted in respect to complexity or construction, destruction, copy
83/// and move semantics, etc. This is reached by deferring construction to
84/// the caller of method #Try, who, in case of a cache miss, is obligated to duly use a
85/// C++ placement-new to construct an entry.
86///
87/// This class provides a forward-iterator type that fetches all currently cached elements.
88/// While this in most cases is not needed, the central interface method #Try also returns an
89/// iterator. While this iterator is always valid, a second returned value indicates whether also
90/// the element the iterator points to is valid. This distinction is necessary because this
91/// container only reserves memory for the cached element, but it does not construct one.
92/// To support elegant construction of elements, the iterator class provides method
93/// \alib{containers::LRUCacheTable::TForwardIterator;Construct}.
94/// Furthermore, methods
95/// \alib{containers::LRUCacheTable::TForwardIterator;Key} and
96/// \alib{containers::LRUCacheTable::TForwardIterator;Mapped} allow access to the stored types.
97///
98/// @see
99/// - Type definitions \alib{containers;LRUCacheSet} and
100/// \alib{containers;LRUCacheMap} based on this type.
101/// - The approach to distinguish between "sets", "maps" and "sets with embedded keys" are
102/// the same with class \b %HashTable. Therefore, the
103/// \ref alib_ns_containers_hashtable_setandmap "documentation of class HashTable", which introduces
104/// the same template parameter \p{TValueDescriptor} and also provides similar type definitions
105/// \b %HashSet and \b %HashMap, is very helpful to understanding the concept of this type.
106///
107///
108/// @tparam TAllocator The \alib{lang;Allocator;allocator type} to use.
109/// @tparam TValueDescriptor Defines the #StoredType, #KeyType, and #MappedType. Furthermore has to
110/// provide methods that extract the key and the mapped value from the
111/// stored type.<br>
112/// For details on required type definitions and method signatures, see
113/// provided implementations
114/// \alib{containers;TIdentDescriptor} and
115/// \alib{containers;TPairDescriptor} as a sample.<br>
116/// The type is published as #DescriptorType.
117/// @tparam THash The hash functor applicable to the key-type defined by
118/// \p{TValueDescriptor}.<br>
119/// Defaults to <c>std::hash<typename TValueDescriptor::KeyType></c>
120/// and is published as #HashType.
121/// @tparam TEqual The comparison functor on the key-type defined by
122/// \p{TValueDescriptor}.<br>
123/// Defaults to <c>std::equal_to<typename TValueDescriptor::KeyType></c>
124/// and is published as #EqualType.
125template< typename TAllocator,
126 typename TValueDescriptor,
127 typename THash = std::hash <typename TValueDescriptor::KeyType>,
128 typename TEqual = std::equal_to<typename TValueDescriptor::KeyType> >
129class LRUCacheTable : public lang::AllocatorMember<TAllocator>
130#if ALIB_DEBUG_CRITICAL_SECTIONS
132#endif
133{
134 protected:
135 /// The type of the base class that stores the allocator.
137
138 public:
139 /// Type definition publishing template parameter \p{TAllocator}.
140 using AllocatorType = TAllocator;
141
142 /// Type definition publishing template parameter \p{TValueDescriptor}.
143 using DescriptorType = TValueDescriptor;
144
145 /// Type definition publishing the stored type of this container as defined with template
146 /// parameter \p{TValueDescriptor}.
147 using StoredType = typename TValueDescriptor::StoredType;
148
149 /// Type definition publishing the key type of this container as defined with template
150 /// parameter \p{TValueDescriptor}.
151 using KeyType = typename TValueDescriptor::KeyType;
152
153 /// Type definition publishing the map type of this container as defined with template
154 /// parameter \p{TValueDescriptor}.
155 using MappedType = typename TValueDescriptor::MappedType;
156
157 /// Type definition publishing template parameter \p{THash}.
158 using HashType = THash;
159
160 /// Type definition publishing template parameter \p{TEqual}.
161 using EqualType = TEqual;
162
163 protected:
164 /// The node type of the cache lists.
165 struct Entry : public lang::SidiNodeBase<Entry>
166 {
167 size_t hashCode; ///< This entries hash code (calculated once on insertion)
168 StoredType data; ///< The data cached.
169 };
170
171 /// Shortcut to a forward list
173
174 /// Pointer to reserved memory for elements. Size is #capacityLists x #capacityEntries.
176
177 /// The next element to use with a cache-miss on a list that is not of full length, yet.
179
180 /// Array of size #capacityLists that holds the list..
182
183 /// The number of LRU-lists.
185
186 /// The number of entries collected in each LRU-list.
188
189 //================================================================================================
190 //=== Iterator implementation
191 //================================================================================================
192
193 /// Templated implementation of \c std::iterator_traits.
194 /// Will be exposed by outer class's definitions
195 /// \alib{containers::LRUCacheTable;Iterator} and
196 /// \alib{containers::LRUCacheTable;ConstIterator}.
197 ///
198 /// As the name of the class indicates, this iterator satisfies the C++ standard library concept
199 /// \https{ForwardIterator,en.cppreference.com/w/cpp/named_req/ForwardIterator}.
200 ///
201 /// @tparam TConstOrMutable A constant or mutable version of #StoredType.
202 template<typename TConstOrMutable>
204 {
205 #if !DOXYGEN
206 friend class LRUCacheTable;
207 #endif
208
209 using iterator_category = std::forward_iterator_tag; ///< Implementation of <c>std::iterator_traits</c>.
210 using value_type = TConstOrMutable ; ///< Implementation of <c>std::iterator_traits</c>.
211 using difference_type = integer ; ///< Implementation of <c>std::iterator_traits</c>.
212 using pointer = TConstOrMutable* ; ///< Implementation of <c>std::iterator_traits</c>.
213 using reference = TConstOrMutable& ; ///< Implementation of <c>std::iterator_traits</c>.
214
215 protected:
216 /// The pointer to the actual cache entry.
218
219 /// The pointer to the actual cache entry.
221
222 /// The actual list.
224
225 public:
226 /// Default constructor.
228
229 /// Copy constructor (default).
230 /// @param other The iterator to assign from.
231 TForwardIterator( const TForwardIterator& other ) =default;
232
233 /// Copy constructor accepting a mutable iterator.
234 /// Available only for the constant version of this iterator.
235 /// @tparam TMutable The type of this constructor's argument.
236 /// @param mutableIt Mutable iterator to copy from.
237 template<typename TMutable>
238 requires std::same_as<TMutable, TForwardIterator<StoredType>>
239 TForwardIterator( const TMutable& mutableIt )
240 : entry ( mutableIt.entry ) {}
241
242 /// Constructor that explicitly sets a valid iterator.
243 /// @param pEntry Pointer to a valid element.
244 /// @param pTable The cache table we belong to.
245 /// @param pListIdx The index of the list that \p{pEntry} belongs to.
246 explicit
247 TForwardIterator( Entry* pEntry, LRUCacheTable* pTable, integer pListIdx )
248 : entry (pEntry)
249 , table (pTable)
250 , listIdx(pListIdx) {}
251
252
253 /// Constructor.
254 /// @param pTable The cache table we belong to.
255 /// @param pListIdx The index of the list to start with.
256 explicit
258 : table (pTable) {
259 while( pListIdx < pTable->capacityLists ) {
260 if( !pTable->lists[pListIdx].isEmpty() ) {
261 listIdx= pListIdx;
262 entry = pTable->lists[pListIdx].first();
263 return;
264 }
265 ++pListIdx;
266 }
267 listIdx= pListIdx;
268 entry = nullptr;
269 }
270
271 /// Copy assignment (default).
272 /// @param other The iterator to assign from.
273 /// @return A reference to this object.
275
276 //########################## To satisfy concept of InputIterator ########################
277
278 /// Prefix increment operator.
279 /// @return A reference to this object.
281 ALIB_ASSERT_ERROR( entry != nullptr, "MONOMEM/LRUCACHE", "Illegal iterator." )
282 entry= entry->next();
283 while( entry == nullptr && ++listIdx < table->capacityLists )
284 entry= table->lists[listIdx].first();
285
286 return *this;
287 }
288
289 /// Postfix increment operator.
290 /// @return An iterator value that is not increased, yet.
292 auto result= TForwardIterator( *this);
293 ++(*this);
294 return result;
295 }
296
297 /// Comparison operator.
298 /// @param other The iterator to compare ourselves to.
299 /// @return \c true if this and the given iterator are pointing to the same entry,
300 /// \c false otherwise.
301 bool operator==( TForwardIterator other) const { return entry == other.entry; }
302
303 /// Comparison operator.
304 /// @param other The iterator to compare ourselves to.
305 /// @return \c true if this and given iterator are not equal, \c false otherwise.
306 bool operator!=( TForwardIterator other) const { return !(*this == other); }
307
308 //############################## access to templated members #############################
309
310 /// Retrieves the stored object that this iterator references.
311 /// @return A reference to the stored object.
312 TConstOrMutable& operator*() const {
313 ALIB_ASSERT_ERROR( entry != nullptr, "MONOMEM/LRUCACHE", "Illegal iterator." )
314 return entry->data;
315 }
316
317 /// Retrieves a pointer to the stored object that this iterator references.
318 /// @return A pointer to the stored object.
319 TConstOrMutable* operator->() const {
320 ALIB_ASSERT_ERROR( entry != nullptr, "MONOMEM/LRUCACHE", "Illegal iterator." )
321 return &entry->data;
322 }
323
324 /// Helper method that performs a placement-new on the data this iterator refers to.
325 /// This method can be used if method #Try indicates a cache miss.
326 ///@tparam TArgs Types of variadic parameters given with parameter \p{args}.
327 ///@param args Variadic parameters to be forwarded to the constructor of the inserted
328 /// instance of type #StoredType.
329 ///@return A reference to the just constructed object.
330 template<typename... TArgs>
331 TConstOrMutable& Construct( TArgs&&... args ) const {
332 ALIB_ASSERT_ERROR( entry != nullptr, "MONOMEM/LRUCACHE", "Illegal iterator." )
333 return *new( &entry->data ) TConstOrMutable(std::forward<TArgs>(args)...);
334 }
335
336 /// Retrieves the stored object that this iterator references.
337 /// @return A reference to the stored object.
338 TConstOrMutable& Value() const {
339 ALIB_ASSERT_ERROR( entry != nullptr, "MONOMEM/LRUCACHE", "Illegal iterator." )
340 return entry->data;
341 }
342
343 /// Retrieves the key-portion of the stored object that this iterator references.
344 /// @return A reference to the key-portion of the stored object.
345 const KeyType& Key() const {
346 ALIB_ASSERT_ERROR( entry != nullptr, "MONOMEM/LRUCACHE", "Illegal iterator." )
347 return TValueDescriptor().Key(entry->data);
348 }
349
350 /// Retrieves the stored object that this iterator references.<br>
351 /// This method is an alias to <c>operator*</c>
352 /// @return A reference to the mapped-portion of the stored object.
354 ALIB_ASSERT_ERROR( entry != nullptr, "MONOMEM/LRUCACHE", "Illegal iterator." )
355 return TValueDescriptor().Mapped(entry->data);
356 }
357 }; // class TForwardIterator
358
359 public:
360 /// The mutable iterator over the cache entries.
361 using Iterator = TForwardIterator < StoredType>;
362
363 /// The constant iterator over the cache entries.
364 using ConstIterator = TForwardIterator <const StoredType>;
365
366 /// Returns an iterator referring to a mutable entry at the start of this cache.
367 /// @return The first of entry in this container.
368 Iterator begin() { return Iterator ( this, 0 ); }
369
370 /// Returns an iterator referring to a mutable, non-existing entry.
371 /// @return The end of the list of entries in this container.
372 Iterator end() { return Iterator ( this, (std::numeric_limits<integer>::max)() ); }
373
374 /// Returns an iterator referring to a constant entry at the start of this container.
375 /// @return The first of entry in this container.
376 ConstIterator begin() const { return ConstIterator( this, 0 ); }
377
378 /// Returns an iterator referring to a constant, non-existing entry.
379 /// @return The end of the list of entries in this container.
380 ConstIterator end() const { return ConstIterator(this, (std::numeric_limits<integer>::max)()); }
381
382 /// Returns an iterator referring to a constant entry at the start of this container.
383 /// @return The first of entry in this container.
384 ConstIterator cbegin() const { return ConstIterator( this, 0 ); }
385
386 /// Returns an iterator referring to a constant, non-existing entry.
387 /// @return The end of the list of entries in this container.
388 ConstIterator cend() const { return ConstIterator(this,(std::numeric_limits<integer>::max)()); }
389
390
391 /// Constructor taking an allocator as well as the sizes forming the capacity of the cache.
392 /// If one of the size parameters is \c 0, no pre-allocation is deferred and #Reserve has
393 /// to be invoked before using this type.
394 /// @param pAllocator The allocator type to use.
395 /// @param tableSize The number of LRU-lists.
396 /// @param listSize The (maximum) size of each list.
397 LRUCacheTable(TAllocator& pAllocator, integer tableSize, integer listSize )
398 : allocBase (pAllocator)
400 ,lang::DbgCriticalSections("LRUCacheTable")
401 #endif
402 , elementPool (nullptr)
403 , nextPoolElement (nullptr)
404 , capacityLists (0)
405 , capacityEntries (0) { Reserve( tableSize, listSize ); }
406
407 /// Constructor omitting the allocator, usable only with heap allocation
408 /// If one of the size parameters is \c 0, no pre-allocation is deferred and #Reserve has
409 /// to be invoked before using this type.
410 /// @param tableSize The number of LRU-lists.
411 /// @param listSize The (maximum) size of each list.
412 LRUCacheTable(integer tableSize, integer listSize )
413 :
415 lang::DbgCriticalSections("LRUCacheTable"),
416 #endif
417 elementPool (nullptr)
418 , nextPoolElement (nullptr)
419 , capacityLists (0)
420 , capacityEntries (0) { Reserve( tableSize, listSize ); }
421
422 /// Destructor. Calls the destructor of each cached value.
424 if( Capacity() == 0 )
425 return;
426 Clear();
427 allocBase::AI().template FreeArray<Entry >(elementPool, Capacity() );
428 allocBase::AI().template FreeArray<ForwardList>(lists , capacityLists );
429 }
430
431 /// Returns the number of lists used for the cache.
432 /// (Given with construction or a later invocation of method #Reserve.)
433 /// @return This caches' size.
435
436 /// Returns the maximum number of entries held in each list.
437 /// (Given with construction or a later invocation of method #Reserve.)
438 /// @return This caches' size.
440
441 /// Returns the product of #CapacityLists and #CapacityEntries.
442 /// (Both given with construction or a later invocation of method #Reserve.)
443 /// @return This caches' size.
445
446 /// Counts the number of stored elements (operates in O(N)).
447 /// @return The number of elements stored in the cache.
448 integer Size() const noexcept {ALIB_DCS_SHARED
449 integer result= 0;
450 for (int i = 0; i < capacityLists; ++i)
451 result+= lists[i].count();
452 return result;
453 }
454
455 /// Changes the size of this cache.
456 /// @param newQtyLists The number of LRU-lists to use.
457 /// @param newQtyEntriesPerList The maximum length of each LRU-list list.
458 void Reserve( integer newQtyLists, integer newQtyEntriesPerList ) {
459 if( CapacityLists() == newQtyLists
460 && CapacityEntries() == newQtyEntriesPerList )
461 return;
462
463 Clear();
465 auto newCapacity= newQtyLists * newQtyEntriesPerList;
466 if( Capacity() != newCapacity) {
467 if( Capacity() != 0 )
468 allocBase::AI(). template FreeArray<Entry>(elementPool, Capacity());
469
470 elementPool = newCapacity ? allocBase::AI(). template AllocArray<Entry>(newCapacity)
471 : nullptr;
472 }
473
474 if( capacityLists != newQtyLists) {
475 if( capacityLists )
476 allocBase::AI(). template FreeArray<ForwardList>(lists, capacityLists );
477 lists= newQtyLists ? allocBase::AI(). template AllocArray<ForwardList>(newQtyLists)
478 : nullptr;
479
480 for( integer i = 0; i < newQtyLists; ++i )
481 lists[i].reset();
482 }
483
484 capacityLists= newQtyLists;
485 capacityEntries= newQtyEntriesPerList;
487 }
488
489 /// Clears this cache.
491 for (integer i = 0; i < capacityLists; ++i) {
492 auto* elem= lists[i].first();
493 while(elem) {
494 lang::Destruct(elem->data);
495 elem= elem->next();
496 }
497 lists[i].reset();
498 }
500 }
501
502 /// Retrieves a value through this cache. The following cases can occur:
503 /// 1. No element with matching \p{key} is found in the cache while not all elements
504 /// of #elementPool are used, yet. In this case the next entry is taken from the pool, and
505 /// the entry is added to the front of the list.
506 /// 2. No element is found while all elements of the #elementPool have been inserted into the
507 /// list already. In this case the last entry of the list is removed, the destructor is
508 /// called on its contents, and the entry is moved to the front of the list.
509 /// 3. The element with matching \p{key} is found. In this case, the entry is moved to the start
510 /// of the list (if not already there).
511 ///
512 /// In cases 1. and 2., this method returns \c false in the first element of the result pair,
513 /// which tells the caller that the value found in the second element has to be constructed.
514 /// This can be done using convenient method
515 /// \alib{containers::LRUCacheTable::TForwardIterator;Construct;Iterator::Construct}.
516 /// Note that besides operator*
517 /// \alib{containers::LRUCacheTable::TForwardIterator;operator*}, the iterator type
518 /// offers methods
519 /// \alib{containers::LRUCacheTable::TForwardIterator;Key} and
520 /// \alib{containers::LRUCacheTable::TForwardIterator;Mapped} to directly access
521 /// corresponding portions of the stored value.
522 ///
523 /// @param key The key value to search for.
524 /// @return A pair of a boolean and an iterator. If the boolean value is \c true, a cached
525 /// entry was found and can be used. If it is \c false, the iterator is valid but
526 /// its data is not! In this case, the caller has to use a placement-new on the
527 /// address of the data receivable with the iterator. This might best be done by
528 /// calling \ref Iterator::Construct.
529 [[nodiscard]]
530 std::pair<bool, Iterator> Try(const KeyType& key) {ALIB_DCS
531 ALIB_ASSERT_ERROR(Capacity() > 0, "MONOMEM","Capacity of LRUCacheTable equals 0 (not set).")
532
533 // start the search below with the first element
534 const size_t keyHash = THash{}(key);
535 const integer listIdx = integer(keyHash % size_t(capacityLists));
536 auto& list = lists[listIdx];
537 Entry* prev2 = nullptr;
538 Entry* prev1 = reinterpret_cast<Entry*>(&list);
539 Entry* actual = list.first();
540 integer cnt = 0;
541
542
543 while( actual != nullptr ) {
544 if ( actual->hashCode == keyHash
545 && TEqual{}(TValueDescriptor().Key(actual->data), key) )
546 {
547 // Move the accessed item to the front
548 if (prev1 != nullptr) {
549 prev1->next( actual->next() );
550 actual->next( list.next() );
551 list.next( actual );
552 }
553 return std::make_pair(true, Iterator(actual, this, listIdx ));
554 }
555 prev2= prev1;
556 prev1= actual;
557 actual= actual->next();
558 ++cnt;
559 }
560
561 // Value not found
562
563 // cache is full? -> take the last entry, change it and push it to the front.
564 if( cnt == capacityEntries ) {
565 prev2->next( nullptr );
566 prev1->data.~StoredType();
567 prev1->hashCode= keyHash;
568 prev1->next( list.next() );
569 list.next( prev1 );
570 return std::make_pair(false, Iterator(list.first(), this, listIdx ));
571 }
572
573 // cache not full yet -> Create new entry
574 Entry* newEntry= nextPoolElement++;
575 newEntry->hashCode= keyHash;
576 newEntry->next(list.next());
577 list.next(newEntry);
578 return std::make_pair(false, Iterator(list.first(), this, listIdx ));
579 }
580
581}; // struct LRUCacheTable
582
583
584
585/// This type definition is a shortcut to \alib{containers;LRUCacheTable}, usable if data
586/// stored in the container does not include a key-portion, and thus the key to the data
587/// retrievable from the cache has to be separately defined.<br>
588/// To achieve this, this type definition aggregates types \p{TKey} and \p{TMapped} into a
589/// <c>std::pair<TKey,TMapped></c>. This is done using special value descriptor type
590/// \alib{containers;TPairDescriptor}.
591///
592/// \see
593/// For a detailed description of this type, see original type
594/// \alib{containers;LRUCacheTable}, as well as alternative type definition
595/// \alib{containers;LRUCacheSet}.
596///
597/// @tparam TAllocator The \alib{lang;Allocator;allocator type} to use.
598/// @tparam TKey The type of the <em>key-portion</em> of the inserted data.<br>
599/// This type is published as \alib{containers;LRUCacheTable::KeyType}.
600/// @tparam TMapped The type of the <em>mapped-portion</em> of the inserted data.<br>
601/// This type is published as
602/// \alib{containers;LRUCacheTable::MappedType}.
603/// @tparam THash The hash functor applicable to \p{TKey}.<br>
604/// Defaults to <c>std::hash<TKey></c> and is published as
605/// \alib{containers;LRUCacheTable::HashType}.
606/// @tparam TEqual The comparison functor on \p{TKey}.<br>
607/// Defaults to <c>std::equal_to<TKey></c> and is published as
608/// \alib{containers;LRUCacheTable::EqualType}.
609template< typename TAllocator,
610 typename TKey, typename TMapped,
611 typename THash = std::hash <TKey>,
612 typename TEqual = std::equal_to<TKey> >
613using LRUCacheMap = LRUCacheTable< TAllocator,
615 THash, TEqual >;
616
617/// This type definition is a shortcut to \alib{containers;LRUCacheTable}, usable if the full
618/// portion of the data stored in the container is used for the comparison of values.
619///
620/// \note
621/// As with this definition template type \p{TKey} equals stored type \p{T}, methods of
622/// target type \alib{containers;LRUCacheTable} that accept an object of template type
623/// \b TKey expect an object of \p{T} when this type type defintion is used.<br>
624/// In case this is not wanted (or possible), and only the true key-portion should be expected
625/// by interface functions such as \alib{containers;LRUCacheTable::Try}, the underlying
626/// original type \alib{containers;LRUCacheTable}) has to be used.
627///
628/// \see
629/// For a detailed description of this type, see original type
630/// \alib{containers;LRUCacheTable}, as well as alternative type definition
631/// \alib{containers;LRUCacheMap}.
632///
633/// @tparam TAllocator The \alib{lang;Allocator;allocator type} to use.
634/// @tparam T The element type stored with this container.
635/// This type is published as
636/// \alib{containers;LRUCacheTable::StoredType} and type definition
637/// \alib{containers;LRUCacheTable::KeyType} becomes a synonym.
638/// @tparam THash The hash functor applicable to \p{T}. If \c void is given, no hashing
639/// is performed.<br>
640/// Defaults to <c>std::hash<T></c> and is published as
641/// \alib{containers;LRUCacheTable::HashType}.
642/// @tparam TEqual The comparison functor on \p{TKey}.<br>
643/// Defaults to <c>std::equal_to<TKey></c> and is published as
644/// \alib{containers;LRUCacheTable::EqualType}.
645template< typename TAllocator,
646 typename T,
647 typename THash = std::hash <T>,
648 typename TEqual = std::equal_to<T> >
649using LRUCacheSet = LRUCacheTable< TAllocator,
651 THash, TEqual >;
652
653} // namespace alib[::containers]
654
655/// Type alias in namespace \b alib.
656template< typename TAllocator,
657 typename TValueDescriptor,
658 typename THash = std::hash <typename TValueDescriptor::KeyType>,
659 typename TEqual = std::equal_to<typename TValueDescriptor::KeyType> >
661
662
663/// Type alias in namespace \b alib.
664template< typename TAllocator,
665 typename TKey, typename TMapped,
666 typename THash = std::hash <TKey>,
667 typename TEqual = std::equal_to<TKey> >
670
671/// Type alias in namespace \b alib.
672template< typename TAllocator,
673 typename T,
674 typename THash = std::hash <T>,
675 typename TEqual = std::equal_to<T> >
678 THash, TEqual >;
679} // namespace [alib]
TConstOrMutable & reference
Implementation of std::iterator_traits.
integer difference_type
Implementation of std::iterator_traits.
TConstOrMutable & Construct(TArgs &&... args) const
TConstOrMutable * pointer
Implementation of std::iterator_traits.
TForwardIterator(Entry *pEntry, LRUCacheTable *pTable, integer pListIdx)
TForwardIterator & operator=(const TForwardIterator &other)=default
bool operator==(TForwardIterator other) const
bool operator!=(TForwardIterator other) const
TForwardIterator(const TForwardIterator &other)=default
std::forward_iterator_tag iterator_category
Implementation of std::iterator_traits.
TConstOrMutable value_type
Implementation of std::iterator_traits.
TForwardIterator(LRUCacheTable *pTable, integer pListIdx)
LRUCacheTable(TAllocator &pAllocator, integer tableSize, integer listSize)
void Clear()
Clears this cache.
std::pair< bool, Iterator > Try(const KeyType &key)
TForwardIterator< StoredType > Iterator
The mutable iterator over the cache entries.
lang::AllocatorMember< TAllocator > allocBase
The type of the base class that stores the allocator.
TForwardIterator< const StoredType > ConstIterator
The constant iterator over the cache entries.
void Reserve(integer newQtyLists, integer newQtyEntriesPerList)
lang::SidiListHook< Entry > ForwardList
Shortcut to a forward list.
TAllocator AllocatorType
Type definition publishing template parameter TAllocator.
LRUCacheTable(integer tableSize, integer listSize)
TValueDescriptor DescriptorType
Type definition publishing template parameter TValueDescriptor.
typename TValueDescriptor::MappedType MappedType
typename TValueDescriptor::StoredType StoredType
typename TValueDescriptor::KeyType KeyType
~LRUCacheTable()
Destructor. Calls the destructor of each cached value.
TEqual EqualType
Type definition publishing template parameter TEqual.
THash HashType
Type definition publishing template parameter THash.
integer Size() const noexcept
#define ALIB_DCS
Definition alib.inl:1392
#define ALIB_EXPORT
Definition alib.inl:497
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1066
#define ALIB_DCS_SHARED
Definition alib.inl:1393
#define ALIB_DEBUG_CRITICAL_SECTIONS
Definition prepro.dox.md:43
LRUCacheTable< TAllocator, containers::TPairDescriptor< TKey, TMapped >, THash, TEqual > LRUCacheMap
LRUCacheTable< TAllocator, TIdentDescriptor< T >, THash, TEqual > LRUCacheSet
void Destruct(T &object)
Definition tmp.inl:82
containers::LRUCacheTable< TAllocator, containers::TPairDescriptor< TKey, TMapped > > LRUCacheMap
Type alias in namespace alib.
containers::LRUCacheTable< TAllocator, TValueDescriptor, THash, TEqual > LRUCacheTable
Type alias in namespace alib.
containers::LRUCacheTable< TAllocator, containers::TIdentDescriptor< T >, THash, TEqual > LRUCacheSet
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
The node type of the cache lists.
size_t hashCode
This entries hash code (calculated once on insertion)
AllocatorInterface< TAllocator > AI() const noexcept
TElement * first() const noexcept
Definition sidilist.inl:218
bool isEmpty() const noexcept
Definition sidilist.inl:210