emd22

Ethan's Item Caching Things

Oct 24th, 2025
253
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.92 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <Core/FxBitset.hpp>
  4. #include <Core/FxHash.hpp>
  5. #include <Core/FxSizedArray.hpp>
  6. #include <map>
  7.  
  8. /**
  9.  * @brief Cache section that can hold any number of items.
  10.  */
  11. template <typename TItemType>
  12. struct FxItemCacheSection_MultiItem
  13. {
  14.     FxBitset ItemsInUse;
  15.     FxSizedArray<TItemType> Items;
  16.  
  17. public:
  18.     void Create(uint32 max_items)
  19.     {
  20.         Items.Create(max_items);
  21.         ItemsInUse.InitZero(max_items);
  22.     }
  23.  
  24.     TItemType* RequestNewItem()
  25.     {
  26.         int index = ItemsInUse.FindNextFreeBit();
  27.  
  28.         if (index == FxBitset::scNoFreeBits) {
  29.             return nullptr;
  30.         }
  31.  
  32.         ItemsInUse.Set(index);
  33.  
  34.         return &Items[index];
  35.     }
  36.  
  37.     void ReleaseItem(TItemType* item)
  38.     {
  39.         auto item_index = Items.GetItemIndex(item);
  40.  
  41.         // If the item was found, clear the bit
  42.         if (item_index != FxSizedArray<TItemType>::scItemNotFound) {
  43.             ItemsInUse.Unset(item_index);
  44.         }
  45.     }
  46. };
  47.  
  48.  
  49. /**
  50.  * @brief Cache section that holds a single item.
  51.  */
  52. template <typename TItemType>
  53. struct FxItemCacheSection_SingleItem
  54. {
  55.     using ItemType = TItemType;
  56.  
  57.     TItemType* pItem = nullptr;
  58.     bool bInUse : 1 = 0;
  59.  
  60. public:
  61.     void Create(uint32 max_items) { pItem = FxMemPool::Alloc<TItemType>(sizeof(TItemType)); }
  62.  
  63.     TItemType* RequestNewItem()
  64.     {
  65.         if (bInUse) {
  66.             return nullptr;
  67.         }
  68.  
  69.         bInUse = true;
  70.  
  71.         return pItem;
  72.     }
  73.  
  74.     void ReleaseItem(TItemType* item)
  75.     {
  76.         if (pItem != item) {
  77.             return;
  78.         }
  79.  
  80.         bInUse = false;
  81.     }
  82. };
  83.  
  84. template <typename T, typename TItemType>
  85. concept C_IsItemCacheSection =
  86.     C_IsAnyBaseOf<T, FxItemCacheSection_MultiItem<TItemType>, FxItemCacheSection_SingleItem<TItemType>>;
  87.  
  88. template <typename TKeyType, typename TItemType, typename TCacheSectionType>
  89.     requires C_IsItemCacheSection<TCacheSectionType, TItemType>
  90. class FxItemCache
  91. {
  92. public:
  93.     using KeyType = TKeyType;
  94.  
  95. public:
  96.     FxItemCache() = default;
  97.  
  98.     void Create(uint32 max_items_per_section) { mItemsPerSection = max_items_per_section; }
  99.  
  100.  
  101.     bool IsItemInCache(TKeyType key)
  102.     {
  103.         auto section_it = mCache.find(key);
  104.  
  105.         return (section_it == mCache.end());
  106.     }
  107.  
  108.     TItemType* RequestGenericItem(TKeyType key)
  109.     {
  110.         auto section_it = mCache.find(key);
  111.  
  112.         if (section_it == mCache.end()) {
  113.             CreateCacheSection(key, mItemsPerSection);
  114.             auto section_it = mCache.find(key);
  115.  
  116.             FxAssert(section_it != mCache.end());
  117.         }
  118.  
  119.         TCacheSectionType& section = section_it->second;
  120.  
  121.         return section.RequestNewItem();
  122.     }
  123.  
  124.     void ReleaseGenericItem(TKeyType key, TItemType* item)
  125.     {
  126.         auto section_it = mCache.find(key);
  127.  
  128.         if (section_it == mCache.end()) {
  129.             FxLogError("Could not find cache section to free from!");
  130.             return;
  131.         }
  132.  
  133.         TCacheSectionType& section = section_it->second;
  134.  
  135.         auto item_index = section.Items.GetItemIndex(item);
  136.  
  137.         // If the item was found, clear the bit
  138.         if (item_index != FxSizedArray<TItemType>::scItemNotFound) {
  139.             section.ItemsInUse.Unset(item_index);
  140.         }
  141.     }
  142.  
  143.     void Destroy();
  144.  
  145.     virtual ~FxItemCache() { Destroy(); }
  146.  
  147. protected:
  148.     TCacheSectionType& CreateCacheSection(TKeyType key, uint32 number_of_items)
  149.     {
  150.         TCacheSectionType cache_section {};
  151.  
  152.         cache_section.Items.InitCapacity(number_of_items);
  153.         cache_section.ItemsInUse.InitZero(number_of_items);
  154.  
  155.         auto iter = mCache.insert({ key, std::move(cache_section) });
  156.  
  157.         return iter.first->second;
  158.     }
  159.  
  160. public:
  161.     std::unordered_map<TKeyType, TCacheSectionType> mCache;
  162.  
  163. protected:
  164.     uint32 mItemsPerSection = 0;
  165. };
  166.  
  167. /**
  168.  * @brief A temporary handle that is available only for the current scope.
  169.  */
  170. template <typename TKeyType, typename TItemType, typename TCacheType>
  171. struct FxItemCacheHandle
  172. {
  173.     using CacheType = TCacheType;
  174.     using KeyType = TKeyType;
  175.  
  176. public:
  177.     FxItemCacheHandle(TCacheType* cache, TItemType* item, TKeyType key) : Item(item), Key(key), mCache(cache) {}
  178.     FxItemCacheHandle(const FxItemCacheHandle& other) = delete;
  179.     FxItemCacheHandle(FxItemCacheHandle&& other)
  180.     {
  181.         Item = other.Item;
  182.         Key = other.Key;
  183.  
  184.         mCache = other.mCache;
  185.  
  186.         other.Item = nullptr;
  187.     }
  188.  
  189.     /**
  190.      * @brief Releases the handle before the destructor is called.
  191.      */
  192.     FX_FORCE_INLINE void Release()
  193.     {
  194.         if (Item == nullptr) {
  195.             return;
  196.         }
  197.  
  198.         mCache->ReleaseGenericItem(Key, Item);
  199.     }
  200.  
  201.     ~FxItemCacheHandle() { Release(); }
  202.  
  203.     TItemType* operator->() { return Item; }
  204.     TItemType& operator*() { return *Item; }
  205.  
  206. public:
  207.     TItemType* Item = nullptr;
  208.     TKeyType Key;
  209.  
  210. private:
  211.     CacheType* mCache;
  212. };
  213.  
Advertisement
Add Comment
Please, Sign In to add comment