using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace GameKit.Utilities
{
///
/// Implement to use type with Caches.
///
public interface IResettable
{
///
/// Resets values when being placed in a cache.
///
void ResetState();
///
/// Initializes values after being retrieved from a cache.
///
void InitializeState();
}
#region Resettable caches.
///
/// Caches collections of multiple generics.
///
public static class ResettableCollectionCaches where T1 : IResettable where T2 : IResettable
{
///
/// Retrieves a collection.
///
///
public static Dictionary RetrieveDictionary() => CollectionCaches.RetrieveDictionary();
///
/// Stores a collection and sets the original reference to default.
/// Method will not execute if value is null.
///
/// Value to store.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void StoreAndDefault(ref Dictionary value)
{
if (value == null)
return;
Store(value);
value = default;
}
///
/// Stores a collection.
///
/// Value to store.
public static void Store(Dictionary value)
{
foreach (KeyValuePair kvp in value)
{
kvp.Key.ResetState();
ObjectCaches.Store(kvp.Key);
kvp.Value.ResetState();
ObjectCaches.Store(kvp.Value);
}
value.Clear();
CollectionCaches.Store(value);
}
}
///
/// Caches collections of multiple generics.
///
public static class ResettableT1CollectionCaches where T1 : IResettable
{
///
/// Retrieves a collection.
///
///
public static Dictionary RetrieveDictionary() => CollectionCaches.RetrieveDictionary();
///
/// Stores a collection and sets the original reference to default.
/// Method will not execute if value is null.
///
/// Value to store.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void StoreAndDefault(ref Dictionary value)
{
if (value == null)
return;
Store(value);
value = default;
}
///
/// Stores a collection.
///
/// Value to store.
public static void Store(Dictionary value)
{
foreach (T1 item in value.Keys)
{
item.ResetState();
ObjectCaches.Store(item);
}
value.Clear();
CollectionCaches.Store(value);
}
}
///
/// Caches collections of multiple generics.
///
public static class ResettableT2CollectionCaches where T2 : IResettable
{
///
/// Retrieves a collection.
///
///
public static Dictionary RetrieveDictionary() => CollectionCaches.RetrieveDictionary();
///
/// Stores a collection and sets the original reference to default.
/// Method will not execute if value is null.
///
/// Value to store.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void StoreAndDefault(ref Dictionary value)
{
if (value == null)
return;
Store(value);
value = default;
}
///
/// Stores a collection.
///
/// Value to store.
public static void Store(Dictionary value)
{
foreach (T2 item in value.Values)
{
item.ResetState();
ObjectCaches.Store(item);
}
value.Clear();
CollectionCaches.Store(value);
}
}
///
/// Caches collections of a single generic.
///
public static class ResettableCollectionCaches where T : IResettable
{
///
/// Retrieves a collection.
///
///
public static T[] RetrieveArray() => CollectionCaches.RetrieveArray();
///
/// Retrieves a collection.
///
///
public static List RetrieveList() => CollectionCaches.RetrieveList();
///
/// Retrieves a collection.
///
///
public static HashSet RetrieveHashSet() => CollectionCaches.RetrieveHashSet();
///
/// Stores a collection and sets the original reference to default.
/// Method will not execute if value is null.
///
/// Value to store.
/// Number of entries in the array from the beginning.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void StoreAndDefault(ref T[] value, int count)
{
if (value == null)
return;
Store(value, count);
value = default;
}
///
/// Stores a collection.
///
/// Value to store.
/// Number of entries in the array from the beginning.
public static void Store(T[] value, int count)
{
for (int i = 0; i < count; i++)
{
value[i].ResetState();
ObjectCaches.Store(value[i]);
}
CollectionCaches.Store(value, count);
}
///
/// Stores a collection and sets the original reference to default.
/// Method will not execute if value is null.
///
/// Value to store.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void StoreAndDefault(ref List value)
{
if (value == null)
return;
Store(value);
value = default;
}
///
/// Stores a collection.
///
/// Value to store.
public static void Store(List value)
{
for (int i = 0; i < value.Count; i++)
{
value[i].ResetState();
ObjectCaches.Store(value[i]);
}
value.Clear();
CollectionCaches.Store(value);
}
///
/// Stores a collection and sets the original reference to default.
/// Method will not execute if value is null.
///
/// Value to store.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void StoreAndDefault(ref HashSet value)
{
if (value == null)
return;
Store(value);
value = default;
}
///
/// Stores a collection.
///
/// Value to store.
public static void Store(HashSet value)
{
foreach (T item in value)
{
item.ResetState();
ObjectCaches.Store(item);
}
value.Clear();
CollectionCaches.Store(value);
}
}
///
/// Caches objects of a single generic.
///
public static class ResettableObjectCaches where T : IResettable
{
///
/// Retrieves an instance of T.
///
public static T Retrieve()
{
T result = ObjectCaches.Retrieve();
result.InitializeState();
return result;
}
///
/// Stores an instance of T and sets the original reference to default.
/// Method will not execute if value is null.
///
/// Value to store.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void StoreAndDefault(ref T value)
{
if (value == null)
return;
Store(value);
value = default;
}
///
/// Stores an instance of T.
///
/// Value to store.
public static void Store(T value)
{
value.ResetState();
ObjectCaches.Store(value);
}
}
#endregion
#region NonResettable caches.
///
/// Caches collections of multiple generics.
///
public static class CollectionCaches
{
///
/// Cache for dictionaries.
///
private readonly static Stack> _dictionaryCache = new Stack>();
///
/// Retrieves a collection.
///
///
public static Dictionary RetrieveDictionary()
{
if (_dictionaryCache.Count == 0)
return new Dictionary();
else
return _dictionaryCache.Pop();
}
///
/// Stores a collection and sets the original reference to default.
/// Method will not execute if value is null.
///
/// Value to store.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void StoreAndDefault(ref Dictionary value)
{
if (value == null)
return;
Store(value);
value = default;
}
///
/// Stores a collection.
///
/// Value to store.
public static void Store(Dictionary value)
{
value.Clear();
_dictionaryCache.Push(value);
}
}
///
/// Caches collections of a single generic.
///
public static class CollectionCaches
{
///
/// Cache for arrays.
///
private readonly static Stack _arrayCache = new Stack();
///
/// Cache for lists.
///
private readonly static Stack> _listCache = new Stack>();
///
/// Cache for hashset.
///
private readonly static Stack> _hashsetCache = new Stack>();
///
/// Retrieves a collection.
///
///
public static T[] RetrieveArray()
{
if (_arrayCache.Count == 0)
return new T[0];
else
return _arrayCache.Pop();
}
///
/// Retrieves a collection.
///
///
public static List RetrieveList()
{
if (_listCache.Count == 0)
return new List();
else
return _listCache.Pop();
}
///
/// Retrieves a collection adding one entry.
///
///
public static List RetrieveList(T entry)
{
List result;
if (_listCache.Count == 0)
result = new List();
else
result = _listCache.Pop();
result.Add(entry);
return result;
}
///
/// Retrieves a HashSet.
///
///
public static HashSet RetrieveHashSet()
{
if (_hashsetCache.Count == 0)
return new HashSet();
else
return _hashsetCache.Pop();
}
///
/// Retrieves a collection adding one entry.
///
///
public static HashSet RetrieveHashSet(T entry)
{
HashSet result;
if (_hashsetCache.Count == 0)
result = new HashSet();
else
result = _hashsetCache.Pop();
result.Add(entry);
return result;
}
///
/// Stores a collection and sets the original reference to default.\
/// Method will not execute if value is null.
///
/// Value to store.
/// Number of entries in the array from the beginning.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void StoreAndDefault(ref T[] value, int count)
{
if (value == null)
return;
Store(value, count);
value = default;
}
///
/// Stores a collection.
///
/// Value to store.
/// Number of entries in the array from the beginning.
public static void Store(T[] value, int count)
{
for (int i = 0; i < count; i++)
value[i] = default;
_arrayCache.Push(value);
}
///
/// Stores a collection and sets the original reference to default.
/// Method will not execute if value is null.
///
/// Value to store.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void StoreAndDefault(ref List value)
{
if (value == null)
return;
Store(value);
value = default;
}
///
/// Stores a collection.
///
/// Value to store.
public static void Store(List value)
{
value.Clear();
_listCache.Push(value);
}
///
/// Stores a collection and sets the original reference to default.
/// Method will not execute if value is null.
///
/// Value to store.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void StoreAndDefault(ref HashSet value)
{
if (value == null)
return;
Store(value);
value = default;
}
///
/// Stores a collection.
///
/// Value to store.
public static void Store(HashSet value)
{
value.Clear();
_hashsetCache.Push(value);
}
}
///
/// Caches objects of a single generic.
///
public static class ObjectCaches
{
///
/// Stack to use.
///
private readonly static Stack _stack = new Stack();
///
/// Returns a value from the stack or creates an instance when the stack is empty.
///
///
public static T Retrieve()
{
if (_stack.Count == 0)
return Activator.CreateInstance();
else
return _stack.Pop();
}
///
/// Stores an instance of T and sets the original reference to default.
/// Method will not execute if value is null.
///
/// Value to store.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void StoreAndDefault(ref T value)
{
if (value == null)
return;
Store(value);
value = default;
}
///
/// Stores a value to the stack.
///
///
public static void Store(T value)
{
_stack.Push(value);
}
}
#endregion
}