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();
}
}
}