Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
#pragma once #include
#include
#include
#include
/** * @brief Cache section that can hold any number of items. */ template
struct FxItemCacheSection_MultiItem { FxBitset ItemsInUse; FxSizedArray
Items; public: void Create(uint32 max_items) { Items.Create(max_items); ItemsInUse.InitZero(max_items); } TItemType* RequestNewItem() { int index = ItemsInUse.FindNextFreeBit(); if (index == FxBitset::scNoFreeBits) { return nullptr; } ItemsInUse.Set(index); return &Items[index]; } void ReleaseItem(TItemType* item) { auto item_index = Items.GetItemIndex(item); // If the item was found, clear the bit if (item_index != FxSizedArray
::scItemNotFound) { ItemsInUse.Unset(item_index); } } }; /** * @brief Cache section that holds a single item. */ template
struct FxItemCacheSection_SingleItem { using ItemType = TItemType; TItemType* pItem = nullptr; bool bInUse : 1 = 0; public: void Create(uint32 max_items) { pItem = FxMemPool::Alloc
(sizeof(TItemType)); } TItemType* RequestNewItem() { if (bInUse) { return nullptr; } bInUse = true; return pItem; } void ReleaseItem(TItemType* item) { if (pItem != item) { return; } bInUse = false; } }; template
concept C_IsItemCacheSection = C_IsAnyBaseOf
, FxItemCacheSection_SingleItem
>; template
requires C_IsItemCacheSection
class FxItemCache { public: using KeyType = TKeyType; public: FxItemCache() = default; void Create(uint32 max_items_per_section) { mItemsPerSection = max_items_per_section; } bool IsItemInCache(TKeyType key) { auto section_it = mCache.find(key); return (section_it == mCache.end()); } TItemType* RequestGenericItem(TKeyType key) { auto section_it = mCache.find(key); if (section_it == mCache.end()) { CreateCacheSection(key, mItemsPerSection); auto section_it = mCache.find(key); FxAssert(section_it != mCache.end()); } TCacheSectionType& section = section_it->second; return section.RequestNewItem(); } void ReleaseGenericItem(TKeyType key, TItemType* item) { auto section_it = mCache.find(key); if (section_it == mCache.end()) { FxLogError("Could not find cache section to free from!"); return; } TCacheSectionType& section = section_it->second; auto item_index = section.Items.GetItemIndex(item); // If the item was found, clear the bit if (item_index != FxSizedArray
::scItemNotFound) { section.ItemsInUse.Unset(item_index); } } void Destroy(); virtual ~FxItemCache() { Destroy(); } protected: TCacheSectionType& CreateCacheSection(TKeyType key, uint32 number_of_items) { TCacheSectionType cache_section {}; cache_section.Items.InitCapacity(number_of_items); cache_section.ItemsInUse.InitZero(number_of_items); auto iter = mCache.insert({ key, std::move(cache_section) }); return iter.first->second; } public: std::unordered_map
mCache; protected: uint32 mItemsPerSection = 0; }; /** * @brief A temporary handle that is available only for the current scope. */ template
struct FxItemCacheHandle { using CacheType = TCacheType; using KeyType = TKeyType; public: FxItemCacheHandle(TCacheType* cache, TItemType* item, TKeyType key) : Item(item), Key(key), mCache(cache) {} FxItemCacheHandle(const FxItemCacheHandle& other) = delete; FxItemCacheHandle(FxItemCacheHandle&& other) { Item = other.Item; Key = other.Key; mCache = other.mCache; other.Item = nullptr; } /** * @brief Releases the handle before the destructor is called. */ FX_FORCE_INLINE void Release() { if (Item == nullptr) { return; } mCache->ReleaseGenericItem(Key, Item); } ~FxItemCacheHandle() { Release(); } TItemType* operator->() { return Item; } TItemType& operator*() { return *Item; } public: TItemType* Item = nullptr; TKeyType Key; private: CacheType* mCache; };
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)