You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
CrowdControl/Assets/Plugins/Animancer/Internal/Collections/ObjectPool.cs

167 lines
6.0 KiB
C#

3 months ago
// Animancer // Copyright 2020 Kybernetik //
//#define ANIMANCER_LOG_OBJECT_POOLING
using System.Collections.Generic;
using UnityEngine;
namespace Animancer
{
/// <summary>Convenience methods for accessing <see cref="ObjectPool{T}"/>.</summary>
public static class ObjectPool
{
/************************************************************************************************************************/
/// <summary>
/// Calls <see cref="ObjectPool{T}.Acquire"/> to get a spare item if there are any, or create a new one.
/// </summary>
public static T Acquire<T>() where T : class, new()
{
return ObjectPool<T>.Acquire();
}
/// <summary>
/// Calls <see cref="ObjectPool{T}.Acquire"/> to get a spare item if there are any, or create a new one.
/// </summary>
public static void Acquire<T>(out T item) where T : class, new()
{
item = ObjectPool<T>.Acquire();
}
/************************************************************************************************************************/
/// <summary>
/// Calls <see cref="ObjectPool{T}.Release"/> to add the `item` to the list of spares so it can be reused.
/// </summary>
public static void Release<T>(T item) where T : class, new()
{
ObjectPool<T>.Release(item);
}
/// <summary>
/// Calls <see cref="ObjectPool{T}.Release"/> to add the `item` to the list of spares so it can be reused.
/// </summary>
public static void Release<T>(ref T item) where T : class, new()
{
if (item != null)
{
ObjectPool<T>.Release(item);
item = null;
}
}
/************************************************************************************************************************/
/// <summary>
/// Calls <see cref="ObjectPool{T}.Acquire"/> to get a spare <see cref="List{T}"/> if
/// there are any or create a new one.
/// </summary>
public static List<T> AcquireList<T>()
{
var list = ObjectPool<List<T>>.Acquire();
Debug.Assert(list.Count == 0,
"A pooled collection is not empty. Collections must not be modified after being released to the pool.");
return list;
}
/// <summary>
/// Calls <see cref="ObjectPool{T}.Release"/> to clear the `list` and mark it as a spare
/// so it can be later returned by <see cref="AcquireList"/>.
/// </summary>
public static void Release<T>(List<T> list)
{
list.Clear();
ObjectPool<List<T>>.Release(list);
}
/************************************************************************************************************************/
/// <summary>
/// Calls <see cref="ObjectPool{T}.Acquire"/> to get a spare <see cref="HashSet{T}"/> if
/// there are any or create a new one.
/// </summary>
public static HashSet<T> AcquireSet<T>()
{
var set = ObjectPool<HashSet<T>>.Acquire();
Debug.Assert(set.Count == 0,
"A pooled collection is not empty. Collections must not be modified after being released to the pool.");
return set;
}
/// <summary>
/// Calls <see cref="ObjectPool{T}.Release"/> to clear the `set` and mark it as a spare
/// so it can be later returned by <see cref="AcquireSet"/>.
/// </summary>
public static void Release<T>(HashSet<T> set)
{
set.Clear();
ObjectPool<HashSet<T>>.Release(set);
}
/************************************************************************************************************************/
}
/// <summary>A simple object pooling system.</summary>
public static class ObjectPool<T> where T : class, new()
{
/************************************************************************************************************************/
private static readonly List<T>
Items = new List<T>();
/************************************************************************************************************************/
/// <summary>The number of spare items currently in the pool.</summary>
public static int Count
{
get { return Items.Count; }
}
/************************************************************************************************************************/
/// <summary>The <see cref="List{T}.Capacity"/> of the internal list of spare items.</summary>
public static int Capacity
{
get { return Items.Capacity; }
set
{
if (Items.Count > value)
Items.RemoveRange(value, Items.Count - value);
Items.Capacity = value;
}
}
/************************************************************************************************************************/
/// <summary>Returns a spare item if there are any, or creates a new one.</summary>
public static T Acquire()
{
var count = Items.Count;
if (count == 0)
{
return new T();
}
else
{
count--;
var item = Items[count];
Items.RemoveAt(count);
return item;
}
}
/************************************************************************************************************************/
/// <summary>Adds the `item` to the list of spares so it can be reused.</summary>
public static void Release(T item)
{
Items.Add(item);
}
/************************************************************************************************************************/
}
}