提交GAS 打算做一个帧同步的GAS

This commit is contained in:
DESKTOP-5RP3AKU\Jisol
2024-10-18 03:16:09 +08:00
parent b0a2e4a900
commit d9b0c78827
726 changed files with 76601 additions and 0 deletions

View File

@@ -0,0 +1,127 @@
using System;
using System.Collections.Concurrent;
using System.Threading;
using UnityEngine;
using UnityEngine.Profiling;
namespace GAS.General
{
public class ArrayPool<T>
{
private readonly int _maxCapacity;
private readonly ConcurrentDictionary<int, Pool> _items = new();
public ArrayPool(int maxCapacity = 1024)
{
if (maxCapacity <= 0)
{
throw new ArgumentOutOfRangeException(nameof(maxCapacity), "maxCapacity must be greater than 0");
}
_maxCapacity = maxCapacity;
}
public T[] Fetch(int length)
{
return _items.TryGetValue(length, out var pool) ? pool.Get() : new T[length];
}
public bool Recycle(T[] obj)
{
if (obj == null)
{
#if UNITY_EDITOR
Debug.LogWarning("ArrayPool<T>.Recycle: obj is null");
#endif
}
else
{
if (!_items.TryGetValue(obj.Length, out var queue))
{
Profiler.BeginSample("ArrayPoolEx<T>.CreateInstance");
queue = _items[obj.Length] = new Pool(obj.Length, _maxCapacity);
Profiler.EndSample();
}
return queue.Return(obj);
}
return false;
}
private class Pool
{
private readonly int _arrayLength;
private readonly int _maxCapacity;
private int _numItems;
private readonly ConcurrentQueue<T[]> _items = new();
private T[] _fastItem;
public Pool(int arrayLength, int maxCapacity = 128)
{
if (_arrayLength < 0)
{
throw new ArgumentOutOfRangeException(nameof(arrayLength), "arrayLength must be greater than or equal to 0");
}
if (maxCapacity <= 0)
{
throw new ArgumentOutOfRangeException(nameof(maxCapacity), "maxCapacity must be greater than 0");
}
_arrayLength = arrayLength;
_maxCapacity = maxCapacity;
}
public T[] Get()
{
var item = _fastItem;
if (item == null || Interlocked.CompareExchange(ref _fastItem, null, item) != item)
{
if (_items.TryDequeue(out item))
{
Interlocked.Decrement(ref _numItems);
}
else
{
Profiler.BeginSample("ArrayPool<T>.Pool<TT>.CreateInstance");
item = new T[_arrayLength];
Profiler.EndSample();
}
}
return item;
}
public bool Return(T[] obj)
{
if (obj == null)
{
return false;
}
if (obj.Length != _arrayLength)
{
Debug.LogWarning($"Array length({obj.Length}) not match({_arrayLength})");
return false;
}
if (_fastItem != null || Interlocked.CompareExchange(ref _fastItem, obj, null) != null)
{
if (Interlocked.Increment(ref _numItems) <= _maxCapacity)
{
_items.Enqueue(obj);
return true;
}
Interlocked.Decrement(ref _numItems);
#if UNITY_EDITOR
Debug.LogWarning($"ArrayPool<{typeof(T).FullName}>.Return: Exceed max capacity({_maxCapacity}), consider increase max capacity.");
#endif
}
return false;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ce03b164d35f457b9ce6ff277db4e735
timeCreated: 1723102741

View File

@@ -0,0 +1,140 @@
using System;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using System.Threading;
using UnityEngine;
using UnityEngine.Profiling;
namespace GAS.General
{
public interface IPool
{
bool IsFromPool { get; set; }
}
public class ObjectPool
{
private static ObjectPool _singleton;
public static ObjectPool Instance => _singleton ??= new ObjectPool();
private readonly ConcurrentDictionary<Type, Pool> _objPool = new();
private readonly Func<Type, Pool> _addPoolFunc = type => new Pool(type, 1024);
public T Fetch<T>() where T : class
{
var type = typeof(T);
var obj = Fetch(type);
return obj as T;
}
public object Fetch(Type type, bool isFromPool = true)
{
object obj;
if (!isFromPool)
{
Profiler.BeginSample("ObjectPool.CreateInstance");
obj = Activator.CreateInstance(type);
Profiler.EndSample();
}
else
{
var pool = GetPool(type);
obj = pool.Get();
if (obj is IPool p)
{
p.IsFromPool = true;
}
}
return obj;
}
public void Recycle(object obj)
{
if (obj is IPool p)
{
if (!p.IsFromPool)
{
return;
}
// 防止多次入池
p.IsFromPool = false;
}
var type = obj.GetType();
var pool = GetPool(type);
pool.Return(obj);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Pool GetPool(Type type)
{
return _objPool.GetOrAdd(type, _addPoolFunc);
}
/// <summary>
/// 线程安全的无锁对象池
/// </summary>
private class Pool
{
private readonly Type _objectType;
private readonly int _maxCapacity;
private int _numItems;
private readonly ConcurrentQueue<object> _items = new();
private object _fastItem;
public Pool(Type objectType, int maxCapacity)
{
if (maxCapacity <= 0)
{
throw new ArgumentOutOfRangeException(nameof(maxCapacity), "maxCapacity must be greater than 0");
}
_objectType = objectType;
_maxCapacity = maxCapacity;
}
public object Get()
{
object item = _fastItem;
if (item == null || Interlocked.CompareExchange(ref _fastItem, null, item) != item)
{
if (_items.TryDequeue(out item))
{
Interlocked.Decrement(ref _numItems);
}
else
{
Profiler.BeginSample("Pool.CreateInstance");
item = Activator.CreateInstance(_objectType);
Profiler.EndSample();
}
}
return item;
}
public bool Return(object obj)
{
if (_fastItem != null || Interlocked.CompareExchange(ref _fastItem, obj, null) != null)
{
if (Interlocked.Increment(ref _numItems) <= _maxCapacity)
{
_items.Enqueue(obj);
return true;
}
Interlocked.Decrement(ref _numItems);
#if UNITY_EDITOR
Debug.LogWarning($"Pool<{_objectType.FullName}>.Return: Exceed max capacity({_maxCapacity}), consider increase max capacity.");
#endif
}
return false;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d258d352f22a4281ab0968530960bee5
timeCreated: 1713765955