using FishNet.Connection; using FishNet.Managing; using FishNet.Object; using FishNet.Serializing.Helping; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using UnityEngine; namespace FishNet.Utility.Performance { /// /// Various ListCache instances that may be used on the Unity thread. /// public static class ListCaches { /// /// Cache collection for NetworkObjects. /// private static Stack> _networkObjectCaches = new Stack>(); /// /// Cache collection for NetworkObjects. /// private static Stack> _networkBehaviourCaches = new Stack>(); /// /// Cache collection for NetworkObjects. /// private static Stack> _transformCaches = new Stack>(); /// /// Cache collection for NetworkConnections. /// private static Stack> _networkConnectionCaches = new Stack>(); /// /// Cache collection for ints. /// private static Stack> _intCaches = new Stack>(); #region GetCache. /// /// Returns a NetworkObject cache. Use StoreCache to return the cache. /// /// public static ListCache GetNetworkObjectCache() { ListCache result; if (_networkObjectCaches.Count == 0) result = new ListCache(); else result = _networkObjectCaches.Pop(); return result; } /// /// Returns a NetworkConnection cache. Use StoreCache to return the cache. /// /// public static ListCache GetNetworkConnectionCache() { ListCache result; if (_networkConnectionCaches.Count == 0) result = new ListCache(); else result = _networkConnectionCaches.Pop(); return result; } /// /// Returns a Transform cache. Use StoreCache to return the cache. /// /// public static ListCache GetTransformCache() { ListCache result; if (_transformCaches.Count == 0) result = new ListCache(); else result = _transformCaches.Pop(); return result; } /// /// Returns a NetworkBehaviour cache. Use StoreCache to return the cache. /// /// public static ListCache GetNetworkBehaviourCache() { ListCache result; if (_networkBehaviourCaches.Count == 0) result = new ListCache(); else result = _networkBehaviourCaches.Pop(); return result; } /// /// Returns an int cache. Use StoreCache to return the cache. /// /// public static ListCache GetIntCache() { ListCache result; if (_intCaches.Count == 0) result = new ListCache(); else result = _intCaches.Pop(); return result; } #endregion #region StoreCache. /// /// Stores a NetworkObject cache. /// /// public static void StoreCache(ListCache cache) { cache.Reset(); _networkObjectCaches.Push(cache); } /// /// Stores a NetworkConnection cache. /// /// public static void StoreCache(ListCache cache) { cache.Reset(); _networkConnectionCaches.Push(cache); } /// /// Stores a Transform cache. /// /// public static void StoreCache(ListCache cache) { cache.Reset(); _transformCaches.Push(cache); } /// /// Stores a NetworkBehaviour cache. /// /// public static void StoreCache(ListCache cache) { cache.Reset(); _networkBehaviourCaches.Push(cache); } /// /// Stores an int cache. /// /// public static void StoreCache(ListCache cache) { cache.Reset(); _intCaches.Push(cache); } #endregion } /// /// Creates a reusable cache of T which auto expands. /// public class ListCache { #region Public. /// /// Collection cache is for. /// public List Collection = new List(); /// /// Entries currently written. /// public int Written => Collection.Count; #endregion #region Private. /// /// Cache for type. /// private Stack _cache = new Stack(); #endregion public ListCache() { Collection = new List(); } public ListCache(int capacity) { Collection = new List(capacity); } /// /// Returns T from cache when possible, or creates a new object when not. /// /// private T Retrieve() { if (_cache.Count > 0) return _cache.Pop(); else return Activator.CreateInstance(); } /// /// Stores value into the cache. /// /// private void Store(T value) { _cache.Push(value); } /// /// Adds a new value to Collection and returns it. /// /// public T AddReference() { T next = Retrieve(); Collection.Add(next); return next; } /// /// Inserts an bject into Collection and returns it. /// /// public T InsertReference(int index) { //Would just be at the end anyway. if (index >= Collection.Count) return AddReference(); T next = Retrieve(); Collection.Insert(index, next); return next; } /// /// Adds value to Collection. /// /// public void AddValue(T value) { Collection.Add(value); } /// /// Inserts value into Collection. /// /// public void InsertValue(int index, T value) { //Would just be at the end anyway. if (index >= Collection.Count) AddValue(value); else Collection.Insert(index, value); } /// /// Adds values to Collection. /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AddValues(ListCache values) { int w = values.Written; List c = values.Collection; for (int i = 0; i < w; i++) AddValue(c[i]); } /// /// Adds values to Collection. /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AddValues(T[] values) { for (int i = 0; i < values.Length; i++) AddValue(values[i]); } /// /// Adds values to Collection. /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AddValues(List values) { for (int i = 0; i < values.Count; i++) AddValue(values[i]); } /// /// Adds values to Collection. /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AddValues(HashSet values) { foreach (T item in values) AddValue(item); } /// /// Adds values to Collection. /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AddValues(ISet values) { foreach (T item in values) AddValue(item); } /// /// Adds values to Collection. /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AddValues(IReadOnlyCollection values) { foreach (T item in values) AddValue(item); } /// /// Resets cache. /// public void Reset() { foreach (T item in Collection) Store(item); Collection.Clear(); } } }