[+] TEngineServer

[+] TEngineServer
This commit is contained in:
ALEXTANG
2023-07-13 17:17:26 +08:00
parent a69f53592e
commit 0c8f3a5f92
790 changed files with 52737 additions and 2533 deletions

View File

@@ -0,0 +1,230 @@
using System;
using System.Collections.Generic;
using System.IO;
#pragma warning disable CS8625
#pragma warning disable CS8618
namespace TEngine.DataStructure
{
/// <summary>
/// 环形缓存自动扩充、不会收缩缓存、所以不要用这个操作过大的IO流
/// 1、环大小8192溢出的会自动增加环的大小。
/// 2、每个块都是一个环形缓存当溢出的时候会自动添加到下一个环中。
/// 3、当读取完成后用过的环会放在缓存中不会销毁掉。
/// </summary>
public sealed class CircularBuffer : Stream, IDisposable
{
private byte[] _lastBuffer;
public const int ChunkSize = 8192; // 环形缓存块大小
private readonly Queue<byte[]> _bufferCache = new Queue<byte[]>();
private readonly Queue<byte[]> _bufferQueue = new Queue<byte[]>();
public int FirstIndex { get; set; }
public int LastIndex { get; set; }
public override long Length
{
get
{
if (_bufferQueue.Count == 0)
{
return 0;
}
return (_bufferQueue.Count - 1) * ChunkSize + LastIndex - FirstIndex;
}
}
public byte[] First
{
get
{
if (_bufferQueue.Count == 0)
{
AddLast();
}
return _bufferQueue.Peek();
}
}
public byte[] Last
{
get
{
if (_bufferQueue.Count == 0)
{
AddLast();
}
return _lastBuffer;
}
}
public void AddLast()
{
var buffer = _bufferCache.Count > 0 ? _bufferCache.Dequeue() : new byte[ChunkSize];
_bufferQueue.Enqueue(buffer);
_lastBuffer = buffer;
}
public void RemoveFirst()
{
_bufferCache.Enqueue(_bufferQueue.Dequeue());
}
public void Read(Stream stream, int count)
{
if (count > Length)
{
throw new Exception($"bufferList length < count, {Length} {count}");
}
var copyCount = 0;
while (copyCount < count)
{
var n = count - copyCount;
if (ChunkSize - FirstIndex > n)
{
stream.Write(First, FirstIndex, n);
FirstIndex += n;
copyCount += n;
}
else
{
stream.Write(First, FirstIndex, ChunkSize - FirstIndex);
copyCount += ChunkSize - FirstIndex;
FirstIndex = 0;
RemoveFirst();
}
}
}
public override int Read(byte[] buffer, int offset, int count)
{
if (buffer.Length < offset + count)
{
throw new Exception($"buffer length < count, buffer length: {buffer.Length} {offset} {count}");
}
var length = Length;
if (length < count)
{
count = (int) length;
}
var copyCount = 0;
while (copyCount < count)
{
var copyLength = count - copyCount;
if (ChunkSize - FirstIndex > copyLength)
{
Array.Copy(First, FirstIndex, buffer, copyCount + offset, copyLength);
FirstIndex += copyLength;
copyCount += copyLength;
continue;
}
Array.Copy(First, FirstIndex, buffer, copyCount + offset, ChunkSize - FirstIndex);
copyCount += ChunkSize - FirstIndex;
FirstIndex = 0;
RemoveFirst();
}
return count;
}
public void Write(byte[] buffer)
{
Write(buffer, 0, buffer.Length);
}
public void Write(Stream stream)
{
var copyCount = 0;
var count = (int) (stream.Length - stream.Position);
while (copyCount < count)
{
if (LastIndex == ChunkSize)
{
AddLast();
LastIndex = 0;
}
var n = count - copyCount;
if (ChunkSize - LastIndex > n)
{
_ = stream.Read(Last, LastIndex, n);
LastIndex += count - copyCount;
copyCount += n;
}
else
{
_ = stream.Read(Last, LastIndex, ChunkSize - LastIndex);
copyCount += ChunkSize - LastIndex;
LastIndex = ChunkSize;
}
}
}
public override void Write(byte[] buffer, int offset, int count)
{
var copyCount = 0;
while (copyCount < count)
{
if (ChunkSize == LastIndex)
{
AddLast();
LastIndex = 0;
}
var byteLength = count - copyCount;
if (ChunkSize - LastIndex > byteLength)
{
Array.Copy(buffer, copyCount + offset, Last, LastIndex, byteLength);
LastIndex += byteLength;
copyCount += byteLength;
}
else
{
Array.Copy(buffer, copyCount + offset, _lastBuffer, LastIndex, ChunkSize - LastIndex);
copyCount += ChunkSize - LastIndex;
LastIndex = ChunkSize;
}
}
}
public override bool CanRead { get; } = true;
public override bool CanSeek { get; } = false;
public override bool CanWrite { get; } = true;
public override long Position { get; set; }
public override void Flush()
{
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public new void Dispose()
{
_bufferQueue.Clear();
_lastBuffer = null;
FirstIndex = 0;
LastIndex = 0;
base.Dispose();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 28188b5e2acefe14a996fb93df6b2fc6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,115 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
#pragma warning disable CS8603
namespace TEngine.DataStructure
{
public class ConcurrentOneToManyListPool<TKey, TValue> : ConcurrentOneToManyList<TKey, TValue>, IDisposable where TKey : notnull
{
private bool _isDispose;
public static ConcurrentOneToManyListPool<TKey, TValue> Create()
{
var a = Pool<ConcurrentOneToManyListPool<TKey, TValue>>.Rent();
a._isDispose = false;
return a;
}
public void Dispose()
{
if (_isDispose)
{
return;
}
_isDispose = true;
Clear();
Pool<ConcurrentOneToManyListPool<TKey, TValue>>.Return(this);
}
}
public class ConcurrentOneToManyList<TKey, TValue> : ConcurrentDictionary<TKey, List<TValue>> where TKey : notnull
{
private readonly Queue<List<TValue>> _queue = new Queue<List<TValue>>();
private readonly int _recyclingLimit = 120;
public ConcurrentOneToManyList()
{
}
/// <summary>
/// 设置最大缓存数量
/// </summary>
/// <param name="recyclingLimit">
/// 1:防止数据量过大、所以超过recyclingLimit的数据还是走GC.
/// 2:设置成0不控制数量全部缓存
/// </param>
public ConcurrentOneToManyList(int recyclingLimit)
{
_recyclingLimit = recyclingLimit;
}
public bool Contains(TKey key, TValue value)
{
TryGetValue(key, out var list);
return list != null && list.Contains(value);
}
public void Add(TKey key, TValue value)
{
if (!TryGetValue(key, out var list))
{
list = Fetch();
list.Add(value);
base[key] = list;
return;
}
list.Add(value);
}
public TValue First(TKey key)
{
return !TryGetValue(key, out var list) ? default : list.FirstOrDefault();
}
public void RemoveValue(TKey key, TValue value)
{
if (!TryGetValue(key, out var list)) return;
list.Remove(value);
if (list.Count == 0) RemoveKey(key);
}
public void RemoveKey(TKey key)
{
if (!TryRemove(key, out var list)) return;
Recycle(list);
}
private List<TValue> Fetch()
{
return _queue.Count <= 0 ? new List<TValue>() : _queue.Dequeue();
}
private void Recycle(List<TValue> list)
{
list.Clear();
if (_recyclingLimit != 0 && _queue.Count > _recyclingLimit) return;
_queue.Enqueue(list);
}
protected new void Clear()
{
base.Clear();
_queue.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f35e267f0b797464e856a9b9244b4215
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,116 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
#pragma warning disable CS8603
namespace TEngine.DataStructure
{
public class ConcurrentOneToManyQueuePool<TKey, TValue> : ConcurrentOneToManyQueue<TKey, TValue>, IDisposable
where TKey : notnull
{
private bool _isDispose;
public static ConcurrentOneToManyQueuePool<TKey, TValue> Create()
{
var a = Pool<ConcurrentOneToManyQueuePool<TKey, TValue>>.Rent();
a._isDispose = false;
return a;
}
public void Dispose()
{
if (_isDispose)
{
return;
}
_isDispose = true;
Clear();
Pool<ConcurrentOneToManyQueue<TKey, TValue>>.Return(this);
}
}
public class ConcurrentOneToManyQueue<TKey, TValue> : ConcurrentDictionary<TKey, Queue<TValue>> where TKey : notnull
{
private readonly Queue<Queue<TValue>> _queue = new Queue<Queue<TValue>>();
private readonly int _recyclingLimit;
/// <summary>
/// 设置最大缓存数量
/// </summary>
/// <param name="recyclingLimit">
/// 1:防止数据量过大、所以超过recyclingLimit的数据还是走GC.
/// 2:设置成0不控制数量全部缓存
/// </param>
public ConcurrentOneToManyQueue(int recyclingLimit = 0)
{
_recyclingLimit = recyclingLimit;
}
public bool Contains(TKey key, TValue value)
{
TryGetValue(key, out var list);
return list != null && list.Contains(value);
}
public void Enqueue(TKey key, TValue value)
{
if (!TryGetValue(key, out var list))
{
list = Fetch();
list.Enqueue(value);
TryAdd(key, list);
return;
}
list.Enqueue(value);
}
public TValue Dequeue(TKey key)
{
if (!TryGetValue(key, out var list) || list.Count == 0) return default;
var value = list.Dequeue();
if (list.Count == 0) RemoveKey(key);
return value;
}
public bool TryDequeue(TKey key, out TValue value)
{
value = Dequeue(key);
return value != null;
}
public void RemoveKey(TKey key)
{
if (!TryGetValue(key, out var list)) return;
TryRemove(key, out _);
Recycle(list);
}
private Queue<TValue> Fetch()
{
return _queue.Count <= 0 ? new Queue<TValue>() : _queue.Dequeue();
}
private void Recycle(Queue<TValue> list)
{
list.Clear();
if (_recyclingLimit != 0 && _queue.Count > _recyclingLimit) return;
_queue.Enqueue(list);
}
protected new void Clear()
{
base.Clear();
_queue.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 162f7b8459ead1940bfaef049f6d8e2c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
namespace TEngine.DataStructure
{
public sealed class EntityList<T> : List<T>, IDisposable where T : IDisposable
{
private bool _isDispose;
public static EntityList<T> Create()
{
var list = Pool<EntityList<T>>.Rent();
list._isDispose = false;
return list;
}
public new void Clear()
{
for (var i = 0; i < this.Count; i++)
{
this[i].Dispose();
}
base.Clear();
}
public void ClearNotDispose()
{
base.Clear();
}
public void Dispose()
{
if (_isDispose)
{
return;
}
_isDispose = true;
Clear();
Pool<EntityList<T>>.Return(this);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 763e9615aee0ac1428f141df39057bf7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
namespace TEngine.DataStructure
{
public sealed class HashSetPool<T> : HashSet<T>, IDisposable
{
private bool _isDispose;
public void Dispose()
{
if (_isDispose)
{
return;
}
_isDispose = true;
Clear();
Pool<HashSetPool<T>>.Return(this);
}
public static HashSetPool<T> Create()
{
var list = Pool<HashSetPool<T>>.Rent();
list._isDispose = false;
return list;
}
}
public sealed class HashSetBasePool<T> : IDisposable
{
public HashSet<T> Set = new HashSet<T>();
public static HashSetBasePool<T> Create()
{
return Pool<HashSetBasePool<T>>.Rent();
}
public void Dispose()
{
Set.Clear();
Pool<HashSetBasePool<T>>.Return(this);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0f2f1a1f1a3f5f246a40be1e7bff871a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
namespace TEngine.DataStructure
{
public sealed class ListPool<T> : List<T>, IDisposable
{
private bool _isDispose;
public void Dispose()
{
if (_isDispose)
{
return;
}
_isDispose = true;
Clear();
Pool<ListPool<T>>.Return(this);
}
public static ListPool<T> Create(params T[] args)
{
var list = Pool<ListPool<T>>.Rent();
list._isDispose = false;
if (args != null) list.AddRange(args);
return list;
}
public static ListPool<T> Create(List<T> args)
{
var list = Pool<ListPool<T>>.Rent();
list._isDispose = false;
if (args != null) list.AddRange(args);
return list;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3014ce89f46d33742acca54a28995242
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,121 @@
using System;
using System.Collections.Generic;
#pragma warning disable CS8600
namespace TEngine.DataStructure
{
public class OneToManyHashSetPool<TKey, TValue> : OneToManyHashSet<TKey, TValue>, IDisposable where TKey : notnull
{
private bool _isDispose;
public static OneToManyHashSetPool<TKey, TValue> Create()
{
var a = Pool<OneToManyHashSetPool<TKey, TValue>>.Rent();
a._isDispose = false;
return a;
}
public void Dispose()
{
if (_isDispose)
{
return;
}
_isDispose = true;
Clear();
Pool<OneToManyHashSetPool<TKey, TValue>>.Return(this);
}
}
public class OneToManyHashSet<TKey, TValue> : Dictionary<TKey, HashSet<TValue>> where TKey : notnull
{
private readonly Queue<HashSet<TValue>> _queue = new Queue<HashSet<TValue>>();
private readonly int _recyclingLimit = 120;
private static HashSet<TValue> _empty = new HashSet<TValue>();
public OneToManyHashSet()
{
}
/// <summary>
/// 设置最大缓存数量
/// </summary>
/// <param name="recyclingLimit">
/// 1:防止数据量过大、所以超过recyclingLimit的数据还是走GC.
/// 2:设置成0不控制数量全部缓存
/// </param>
public OneToManyHashSet(int recyclingLimit)
{
_recyclingLimit = recyclingLimit;
}
public bool Contains(TKey key, TValue value)
{
TryGetValue(key, out var list);
return list != null && list.Contains(value);
}
public void Add(TKey key, TValue value)
{
if (!TryGetValue(key, out var list))
{
list = Fetch();
list.Add(value);
Add(key, list);
return;
}
list.Add(value);
}
public void RemoveValue(TKey key, TValue value)
{
if (!TryGetValue(key, out var list)) return;
list.Remove(value);
if (list.Count == 0) RemoveKey(key);
}
public void RemoveKey(TKey key)
{
if (!TryGetValue(key, out var list)) return;
Remove(key);
Recycle(list);
}
public HashSet<TValue> GetValue(TKey key)
{
if (TryGetValue(key, out HashSet<TValue> value))
{
return value;
}
return _empty;
}
private HashSet<TValue> Fetch()
{
return _queue.Count <= 0 ? new HashSet<TValue>() : _queue.Dequeue();
}
private void Recycle(HashSet<TValue> list)
{
list.Clear();
if (_recyclingLimit != 0 && _queue.Count > _recyclingLimit) return;
_queue.Enqueue(list);
}
protected new void Clear()
{
base.Clear();
_queue.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 393302e735c4b2f4885c21dd4235b64a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
using System.Linq;
#pragma warning disable CS8600
#pragma warning disable CS8603
namespace TEngine.DataStructure
{
public class OneToManyListPool<TKey, TValue> : OneToManyList<TKey, TValue>, IDisposable where TKey : notnull
{
private bool _isDispose;
public static OneToManyListPool<TKey, TValue> Create()
{
var list = Pool<OneToManyListPool<TKey, TValue>>.Rent();
list._isDispose = false;
return list;
}
public void Dispose()
{
if (_isDispose)
{
return;
}
_isDispose = true;
Clear();
Pool<OneToManyListPool<TKey, TValue>>.Return(this);
}
}
public class OneToManyList<TKey, TValue> : Dictionary<TKey, List<TValue>> where TKey : notnull
{
private readonly Queue<List<TValue>> _queue = new Queue<List<TValue>>();
private readonly int _recyclingLimit = 120;
private static List<TValue> _empty = new List<TValue>();
public OneToManyList()
{
}
/// <summary>
/// 设置最大缓存数量
/// </summary>
/// <param name="recyclingLimit">
/// 1:防止数据量过大、所以超过recyclingLimit的数据还是走GC.
/// 2:设置成0不控制数量全部缓存
/// </param>
public OneToManyList(int recyclingLimit)
{
_recyclingLimit = recyclingLimit;
}
public bool Contains(TKey key, TValue value)
{
TryGetValue(key, out var list);
return list != null && list.Contains(value);
}
public void Add(TKey key, TValue value)
{
if (!TryGetValue(key, out var list))
{
list = Fetch();
list.Add(value);
Add(key, list);
return;
}
list.Add(value);
}
public TValue First(TKey key)
{
return !TryGetValue(key, out var list) ? default : list.FirstOrDefault();
}
public bool RemoveValue(TKey key, TValue value)
{
if (!TryGetValue(key, out var list))
{
return true;
}
var isRemove = list.Remove(value);
if (list.Count == 0)
{
isRemove = RemoveByKey(key);
}
return isRemove;
}
public bool RemoveByKey(TKey key)
{
if (!TryGetValue(key, out var list))
{
return false;
}
Remove(key);
Recycle(list);
return true;
}
public List<TValue> GetValues(TKey key)
{
if (TryGetValue(key, out List<TValue> list))
{
return list;
}
return _empty;
}
public new void Clear()
{
foreach (var keyValuePair in this) Recycle(keyValuePair.Value);
base.Clear();
}
private List<TValue> Fetch()
{
return _queue.Count <= 0 ? new List<TValue>() : _queue.Dequeue();
}
private void Recycle(List<TValue> list)
{
list.Clear();
if (_recyclingLimit != 0 && _queue.Count > _recyclingLimit) return;
_queue.Enqueue(list);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7a6fdf7c8423c0e41804022df95a399d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
#pragma warning disable CS8603
namespace TEngine.DataStructure
{
public class OneToManyQueuePool<TKey, TValue> : OneToManyQueue<TKey, TValue>, IDisposable where TKey : notnull
{
private bool _isDispose;
public static OneToManyQueuePool<TKey, TValue> Create()
{
var a = Pool<OneToManyQueuePool<TKey, TValue>>.Rent();
a._isDispose = false;
return a;
}
public void Dispose()
{
if (_isDispose)
{
return;
}
_isDispose = true;
Clear();
Pool<OneToManyQueuePool<TKey, TValue>>.Return(this);
}
}
public class OneToManyQueue<TKey, TValue> : Dictionary<TKey, Queue<TValue>> where TKey : notnull
{
private readonly Queue<Queue<TValue>> _queue = new Queue<Queue<TValue>>();
private readonly int _recyclingLimit;
/// <summary>
/// 设置最大缓存数量
/// </summary>
/// <param name="recyclingLimit">
/// 1:防止数据量过大、所以超过recyclingLimit的数据还是走GC.
/// 2:设置成0不控制数量全部缓存
/// </param>
public OneToManyQueue(int recyclingLimit = 0)
{
_recyclingLimit = recyclingLimit;
}
public bool Contains(TKey key, TValue value)
{
TryGetValue(key, out var list);
return list != null && list.Contains(value);
}
public void Enqueue(TKey key, TValue value)
{
if (!TryGetValue(key, out var list))
{
list = Fetch();
list.Enqueue(value);
Add(key, list);
return;
}
list.Enqueue(value);
}
public TValue Dequeue(TKey key)
{
if (!TryGetValue(key, out var list) || list.Count == 0)
{
return default;
}
var value = list.Dequeue();
if (list.Count == 0)
{
RemoveKey(key);
}
return value;
}
public bool TryDequeue(TKey key, out TValue value)
{
value = Dequeue(key);
return value != null;
}
public void RemoveKey(TKey key)
{
if (!TryGetValue(key, out var list)) return;
Remove(key);
Recycle(list);
}
private Queue<TValue> Fetch()
{
return _queue.Count <= 0 ? new Queue<TValue>() : _queue.Dequeue();
}
private void Recycle(Queue<TValue> list)
{
list.Clear();
if (_recyclingLimit != 0 && _queue.Count > _recyclingLimit) return;
_queue.Enqueue(list);
}
protected new void Clear()
{
base.Clear();
_queue.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 35d6a9fde65a99143b0abf6d9569c462
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,537 @@
// #if UNITY_5_3_OR_NEWER
// using System;
// using System.Collections;
// using System.Collections.Generic;
// using System.Diagnostics;
// using System.Diagnostics.CodeAnalysis;
// using System.Linq;
// using System.Runtime.CompilerServices;
// #pragma warning disable CS8600
//
// namespace System.Collections.Generic
// {
// public class PriorityQueue<TElement, TPriority>
// {
// private const int DefaultCapacity = 4;
//
// private readonly IComparer<TPriority> _priorityComparer;
//
// private HeapEntry[] _heap;
// private int _count;
// private int _version;
//
// private UnorderedItemsCollection? _unorderedItemsCollection;
//
// #region Constructors
// public PriorityQueue() : this(0, null)
// {
//
// }
//
// // public PriorityQueue(int initialCapacity) : this(initialCapacity, null)
// // {
// //
// // }
//
// // public PriorityQueue(IComparer<TPriority>? comparer) : this(0, comparer)
// // {
// //
// // }
//
// // public PriorityQueue(int initialCapacity, IComparer<TPriority>? comparer)
// // {
// // if (initialCapacity < 0)
// // {
// // throw new ArgumentOutOfRangeException(nameof(initialCapacity));
// // }
// //
// // if (initialCapacity == 0)
// // {
// // _heap = Array.Empty<HeapEntry>();
// // }
// // else
// // {
// // _heap = new HeapEntry[initialCapacity];
// // }
// //
// // _priorityComparer = comparer ?? Comparer<TPriority>.Default;
// // }
//
// public PriorityQueue(IEnumerable<(TElement Element, TPriority Priority)> values) : this(values, null)
// {
//
// }
//
// public PriorityQueue(IEnumerable<(TElement Element, TPriority Priority)> values, IComparer<TPriority>? comparer)
// {
// _priorityComparer = comparer ?? Comparer<TPriority>.Default;
// _heap = Array.Empty<HeapEntry>();
// _count = 0;
//
// AppendRaw(values);
// Heapify();
// }
// #endregion
//
// public int Count => _count;
// public IComparer<TPriority> Comparer => _priorityComparer;
//
// public void Enqueue(TElement element, TPriority priority)
// {
// _version++;
// if (_count == _heap.Length)
// {
// Resize(ref _heap);
// }
//
// SiftUp(index: _count++, in element, in priority);
// }
//
// public void EnqueueRange(IEnumerable<(TElement Element, TPriority Priority)> values)
// {
// _version++;
// if (_count == 0)
// {
// AppendRaw(values);
// Heapify();
// }
// else
// {
// foreach ((TElement element, TPriority priority) in values)
// {
// if (_count == _heap.Length)
// {
// Resize(ref _heap);
// }
//
// SiftUp(index: _count++, in element, in priority);
// }
// }
// }
//
// // TODO optimize
// public void EnqueueRange(IEnumerable<TElement> elements, TPriority priority) => EnqueueRange(elements.Select(e => (e, priority)));
//
// public TElement Peek()
// {
// if (_count == 0)
// {
// throw new InvalidOperationException();
// }
//
// return _heap[0].Element;
// }
//
// public bool TryPeek([MaybeNullWhen(false)] out TElement element, [MaybeNullWhen(false)] out TPriority priority)
// {
// if (_count == 0)
// {
// element = default;
// priority = default;
// return false;
// }
//
// (element, priority) = _heap[0];
// return true;
// }
//
// public TElement Dequeue()
// {
// if (_count == 0)
// {
// throw new InvalidOperationException();
// }
//
// _version++;
// RemoveIndex(index: 0, out TElement result, out _);
// return result;
// }
//
// public bool TryDequeue([MaybeNullWhen(false)] out TElement element, [MaybeNullWhen(false)] out TPriority priority)
// {
// if (_count == 0)
// {
// element = default;
// priority = default;
// return false;
// }
//
// _version++;
// RemoveIndex(index: 0, out element, out priority);
// return true;
// }
//
// public TElement EnqueueDequeue(TElement element, TPriority priority)
// {
// if (_count == 0)
// {
// return element;
// }
//
// ref HeapEntry minEntry = ref _heap[0];
// if (_priorityComparer.Compare(priority, minEntry.Priority) <= 0)
// {
// return element;
// }
//
// _version++;
// TElement minElement = minEntry.Element;
// #if SIFTDOWN_EMPTY_NODES
// SiftDownHeapPropertyRequired(index: 0, in element, in priority);
// #else
// SiftDown(index: 0, in element, in priority);
// #endif
// return minElement;
// }
//
// public void Clear()
// {
// _version++;
// if (_count > 0)
// {
// //if (RuntimeHelpers.IsReferenceOrContainsReferences<HeapEntry>())
// {
// Array.Clear(_heap, 0, _count);
// }
//
// _count = 0;
// }
// }
//
// public void TrimExcess()
// {
// int count = _count;
// int threshold = (int)(((double)_heap.Length) * 0.9);
// if (count < threshold)
// {
// Array.Resize(ref _heap, count);
// }
// }
//
// public void EnsureCapacity(int capacity)
// {
// if (capacity < 0)
// {
// throw new ArgumentOutOfRangeException();
// }
//
// if (capacity > _heap.Length)
// {
// Array.Resize(ref _heap, capacity);
// }
// }
//
// public UnorderedItemsCollection UnorderedItems => _unorderedItemsCollection ??= new UnorderedItemsCollection(this);
//
// public class UnorderedItemsCollection : IReadOnlyCollection<(TElement Element, TPriority Priority)>, ICollection
// {
// private readonly PriorityQueue<TElement, TPriority> _priorityQueue;
//
// internal UnorderedItemsCollection(PriorityQueue<TElement, TPriority> priorityQueue)
// {
// _priorityQueue = priorityQueue;
// }
//
// public int Count => _priorityQueue.Count;
// public bool IsSynchronized => false;
// public object SyncRoot => _priorityQueue;
//
// public Enumerator GetEnumerator() => new Enumerator(_priorityQueue);
// IEnumerator<(TElement Element, TPriority Priority)> IEnumerable<(TElement Element, TPriority Priority)>.GetEnumerator() => new Enumerator(_priorityQueue);
// IEnumerator IEnumerable.GetEnumerator() => new Enumerator(_priorityQueue);
//
// bool ICollection.IsSynchronized => false;
// object ICollection.SyncRoot => this;
// void ICollection.CopyTo(Array array, int index)
// {
// if (array == null)
// throw new ArgumentNullException(nameof(array));
// if (array.Rank != 1)
// throw new ArgumentException("SR.Arg_RankMultiDimNotSupported", nameof(array));
// if (index < 0)
// throw new ArgumentOutOfRangeException(nameof(index), "SR.ArgumentOutOfRange_Index");
//
// int arrayLen = array.Length;
// if (arrayLen - index < _priorityQueue._count)
// throw new ArgumentException("SR.Argument_InvalidOffLen");
//
// int numToCopy = _priorityQueue._count;
// HeapEntry[] heap = _priorityQueue._heap;
//
// for (int i = 0; i < numToCopy; i++)
// {
// ref HeapEntry entry = ref heap[i];
// array.SetValue((entry.Element, entry.Priority), index + i);
// }
// }
//
// public struct Enumerator : IEnumerator<(TElement Element, TPriority Priority)>, IEnumerator
// {
// private readonly PriorityQueue<TElement, TPriority> _queue;
// private readonly int _version;
// private int _index;
// private (TElement Element, TPriority Priority) _current;
//
// internal Enumerator(PriorityQueue<TElement, TPriority> queue)
// {
// _version = queue._version;
// _queue = queue;
// _index = 0;
// _current = default;
// }
//
// public bool MoveNext()
// {
// PriorityQueue<TElement, TPriority> queue = _queue;
//
// if (queue._version == _version && _index < queue._count)
// {
// ref HeapEntry entry = ref queue._heap[_index];
// _current = (entry.Element, entry.Priority);
// _index++;
// return true;
// }
//
// if (queue._version != _version)
// {
// throw new InvalidOperationException("collection was modified");
// }
//
// return false;
// }
//
// public (TElement Element, TPriority Priority) Current => _current;
// object IEnumerator.Current => _current;
//
// public void Reset()
// {
// if (_queue._version != _version)
// {
// throw new InvalidOperationException("collection was modified");
// }
//
// _index = 0;
// _current = default;
// }
//
// public void Dispose()
// {
// }
// }
// }
//
// #region Private Methods
// private void Heapify()
// {
// HeapEntry[] heap = _heap;
//
// for (int i = (_count - 1) >> 2; i >= 0; i--)
// {
// HeapEntry entry = heap[i]; // ensure struct is copied before sifting
// SiftDown(i, in entry.Element, in entry.Priority);
// }
// }
//
// private void AppendRaw(IEnumerable<(TElement Element, TPriority Priority)> values)
// {
// // TODO: specialize on ICollection types
// var heap = _heap;
// int count = _count;
//
// foreach ((TElement element, TPriority priority) in values)
// {
// if (count == heap.Length)
// {
// Resize(ref heap);
// }
//
// ref HeapEntry entry = ref heap[count];
// entry.Element = element;
// entry.Priority = priority;
// count++;
// }
//
// _heap = heap;
// _count = count;
// }
//
// private void RemoveIndex(int index, out TElement element, out TPriority priority)
// {
// Debug.Assert(index < _count);
//
// (element, priority) = _heap[index];
//
// int lastElementPos = --_count;
// ref HeapEntry lastElement = ref _heap[lastElementPos];
//
// if (lastElementPos > 0)
// {
// #if SIFTDOWN_EMPTY_NODES
// SiftDownHeapPropertyRequired(index, in lastElement.Element, in lastElement.Priority);
// #else
// SiftDown(index, in lastElement.Element, in lastElement.Priority);
// #endif
// }
//
// //if (RuntimeHelpers.IsReferenceOrContainsReferences<HeapEntry>())
// {
// lastElement = default;
// }
// }
//
// private void SiftUp(int index, in TElement element, in TPriority priority)
// {
// while (index > 0)
// {
// int parentIndex = (index - 1) >> 2;
// ref HeapEntry parent = ref _heap[parentIndex];
//
// if (_priorityComparer.Compare(parent.Priority, priority) <= 0)
// {
// // parentPriority <= priority, heap property is satisfed
// break;
// }
//
// _heap[index] = parent;
// index = parentIndex;
// }
//
// ref HeapEntry entry = ref _heap[index];
// entry.Element = element;
// entry.Priority = priority;
// }
//
// private void SiftDown(int index, in TElement element, in TPriority priority)
// {
// int minChildIndex;
// int count = _count;
// HeapEntry[] heap = _heap;
//
// while ((minChildIndex = (index << 2) + 1) < count)
// {
// // find the child with the minimal priority
// ref HeapEntry minChild = ref heap[minChildIndex];
// int childUpperBound = Math.Min(count, minChildIndex + 4);
//
// for (int nextChildIndex = minChildIndex + 1; nextChildIndex < childUpperBound; nextChildIndex++)
// {
// ref HeapEntry nextChild = ref heap[nextChildIndex];
// if (_priorityComparer.Compare(nextChild.Priority, minChild.Priority) < 0)
// {
// minChildIndex = nextChildIndex;
// minChild = ref nextChild;
// }
// }
//
// // compare with inserted priority
// if (_priorityComparer.Compare(priority, minChild.Priority) <= 0)
// {
// // priority <= minChild, heap property is satisfied
// break;
// }
//
// heap[index] = minChild;
// index = minChildIndex;
// }
//
// ref HeapEntry entry = ref heap[index];
// entry.Element = element;
// entry.Priority = priority;
// }
//
// #if SIFTDOWN_EMPTY_NODES
// private void SiftDownHeapPropertyRequired(int index, in TElement element, in TPriority priority)
// {
// int emptyNodeIndex = SiftDownEmptyNode(index);
// SiftUp(emptyNodeIndex, in element, in priority);
// }
//
// private int SiftDownEmptyNode(int emptyNodeIndex)
// {
// int count = _count;
// int minChildIndex;
// HeapEntry[] heap = _heap;
//
// while ((minChildIndex = (emptyNodeIndex << 2) + 1) < count)
// {
// // find the child with the minimal priority
// ref HeapEntry minChild = ref heap[minChildIndex];
// int childUpperBound = Math.Min(count, minChildIndex + 4);
//
// for (int nextChildIndex = minChildIndex + 1; nextChildIndex < childUpperBound; nextChildIndex++)
// {
// ref HeapEntry nextChild = ref heap[nextChildIndex];
// if (_priorityComparer.Compare(nextChild.Priority, minChild.Priority) < 0)
// {
// minChildIndex = nextChildIndex;
// minChild = ref nextChild;
// }
// }
//
// heap[emptyNodeIndex] = minChild;
// emptyNodeIndex = minChildIndex;
// }
//
// return emptyNodeIndex;
// }
// #endif
//
// private void Resize(ref HeapEntry[] heap)
// {
// int newSize = heap.Length == 0 ? DefaultCapacity : 2 * heap.Length;
// Array.Resize(ref heap, newSize);
// }
//
// private struct HeapEntry
// {
// public TElement Element;
// public TPriority Priority;
//
// public void Deconstruct(out TElement element, out TPriority priority)
// {
// element = Element;
// priority = Priority;
// }
// }
//
// #if DEBUG
// public void ValidateInternalState()
// {
// if (_heap.Length < _count)
// {
// throw new Exception("invalid elements array length");
// }
//
// foreach ((var element, var idx) in _heap.Select((x, i) => (x.Element, i)).Skip(_count))
// {
// if (!IsDefault(element))
// {
// throw new Exception($"Non-zero element '{element}' at index {idx}.");
// }
// }
//
// foreach ((var priority, var idx) in _heap.Select((x, i) => (x.Priority, i)).Skip(_count))
// {
// if (!IsDefault(priority))
// {
// throw new Exception($"Non-zero priority '{priority}' at index {idx}.");
// }
// }
//
// static bool IsDefault<T>(T value)
// {
// T defaultVal = default;
//
// if (defaultVal is null)
// {
// return value is null;
// }
//
// return value!.Equals(defaultVal);
// }
// }
// #endif
// #endregion
// }
// }
// #endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1e7e9292b9c27384d9aed58ea3d5098d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
namespace TEngine.DataStructure
{
public sealed class ReuseList<T> : List<T>, IDisposable
{
private bool _isDispose;
public static ReuseList<T> Create()
{
var list = Pool<ReuseList<T>>.Rent();
list._isDispose = false;
return list;
}
public void Dispose()
{
if (_isDispose)
{
return;
}
_isDispose = true;
Clear();
Pool<ReuseList<T>>.Return(this);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fe34244ec94ec0240a92d11c66f9d94e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,139 @@
using System;
using System.Collections.Generic;
using System.Linq;
#pragma warning disable CS8603
namespace TEngine.DataStructure
{
public class SortedConcurrentOneToManyListPool<TKey, TValue> : SortedConcurrentOneToManyList<TKey, TValue>,
IDisposable where TKey : notnull
{
private bool _isDispose;
public static SortedConcurrentOneToManyListPool<TKey, TValue> Create()
{
var a = Pool<SortedConcurrentOneToManyListPool<TKey, TValue>>.Rent();
a._isDispose = false;
return a;
}
public void Dispose()
{
if (_isDispose)
{
return;
}
_isDispose = true;
Clear();
Pool<SortedConcurrentOneToManyListPool<TKey, TValue>>.Return(this);
}
}
public class SortedConcurrentOneToManyList<TKey, TValue> : SortedDictionary<TKey, List<TValue>> where TKey : notnull
{
private readonly object _lockObject = new object();
private readonly Queue<List<TValue>> _queue = new Queue<List<TValue>>();
private readonly int _recyclingLimit;
public SortedConcurrentOneToManyList()
{
}
/// <summary>
/// 设置最大缓存数量
/// </summary>
/// <param name="recyclingLimit">
/// 1:防止数据量过大、所以超过recyclingLimit的数据还是走GC.
/// 2:设置成0不控制数量全部缓存
/// </param>
public SortedConcurrentOneToManyList(int recyclingLimit = 0)
{
_recyclingLimit = recyclingLimit;
}
public bool Contains(TKey key, TValue value)
{
lock (_lockObject)
{
TryGetValue(key, out var list);
return list != null && list.Contains(value);
}
}
public void Add(TKey key, TValue value)
{
lock (_lockObject)
{
if (!TryGetValue(key, out var list))
{
list = Fetch();
list.Add(value);
base[key] = list;
return;
}
list.Add(value);
}
}
public TValue First(TKey key)
{
lock (_lockObject)
{
return !TryGetValue(key, out var list) ? default : list.FirstOrDefault();
}
}
public void RemoveValue(TKey key, TValue value)
{
lock (_lockObject)
{
if (!TryGetValue(key, out var list)) return;
list.Remove(value);
if (list.Count == 0) RemoveKey(key);
}
}
public void RemoveKey(TKey key)
{
lock (_lockObject)
{
if (!TryGetValue(key, out var list)) return;
Remove(key);
Recycle(list);
}
}
private List<TValue> Fetch()
{
lock (_lockObject)
{
return _queue.Count <= 0 ? new List<TValue>() : _queue.Dequeue();
}
}
private void Recycle(List<TValue> list)
{
lock (_lockObject)
{
list.Clear();
if (_recyclingLimit != 0 && _queue.Count > _recyclingLimit) return;
_queue.Enqueue(list);
}
}
protected new void Clear()
{
base.Clear();
_queue.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 24aa8bc8ac4d8584cb9ceb23a51c78fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
namespace TEngine.DataStructure
{
public class SortedOneToManyHashSetPool<TKey, TValue> : SortedOneToManyHashSet<TKey, TValue>, IDisposable
where TKey : notnull
{
private bool _isDispose;
public static SortedOneToManyHashSetPool<TKey, TValue> Create()
{
var a = Pool<SortedOneToManyHashSetPool<TKey, TValue>>.Rent();
a._isDispose = false;
return a;
}
public void Dispose()
{
if (_isDispose)
{
return;
}
_isDispose = true;
Clear();
Pool<SortedOneToManyHashSetPool<TKey, TValue>>.Return(this);
}
}
public class SortedOneToManyHashSet<TKey, TValue> : SortedDictionary<TKey, HashSet<TValue>> where TKey : notnull
{
private readonly Queue<HashSet<TValue>> _queue = new Queue<HashSet<TValue>>();
private readonly int _recyclingLimit = 120;
public SortedOneToManyHashSet()
{
}
/// <summary>
/// 设置最大缓存数量
/// </summary>
/// <param name="recyclingLimit">
/// 1:防止数据量过大、所以超过recyclingLimit的数据还是走GC.
/// 2:设置成0不控制数量全部缓存
/// </param>
public SortedOneToManyHashSet(int recyclingLimit)
{
_recyclingLimit = recyclingLimit;
}
public bool Contains(TKey key, TValue value)
{
TryGetValue(key, out var list);
return list != null && list.Contains(value);
}
public void Add(TKey key, TValue value)
{
if (!TryGetValue(key, out var list))
{
list = Fetch();
list.Add(value);
Add(key, list);
return;
}
list.Add(value);
}
public void RemoveValue(TKey key, TValue value)
{
if (!TryGetValue(key, out var list)) return;
list.Remove(value);
if (list.Count == 0) RemoveKey(key);
}
public void RemoveKey(TKey key)
{
if (!TryGetValue(key, out var list)) return;
Remove(key);
Recycle(list);
}
private HashSet<TValue> Fetch()
{
return _queue.Count <= 0 ? new HashSet<TValue>() : _queue.Dequeue();
}
private void Recycle(HashSet<TValue> list)
{
list.Clear();
if (_recyclingLimit != 0 && _queue.Count > _recyclingLimit) return;
_queue.Enqueue(list);
}
protected new void Clear()
{
base.Clear();
_queue.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ddf73601eadf11349b77b78a4d91f35a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
using System.Linq;
#pragma warning disable CS8603
namespace TEngine.DataStructure
{
public class SortedOneToManyListPool<TKey, TValue> : SortedOneToManyList<TKey, TValue>, IDisposable
where TKey : notnull
{
private bool _isDispose;
public static SortedOneToManyListPool<TKey, TValue> Create()
{
var a = Pool<SortedOneToManyListPool<TKey, TValue>>.Rent();
a._isDispose = false;
return a;
}
public void Dispose()
{
if (_isDispose)
{
return;
}
_isDispose = true;
Clear();
Pool<SortedOneToManyListPool<TKey, TValue>>.Return(this);
}
}
public class SortedOneToManyList<TKey, TValue> : SortedDictionary<TKey, List<TValue>> where TKey : notnull
{
private readonly Queue<List<TValue>> _queue = new Queue<List<TValue>>();
private readonly int _recyclingLimit;
public SortedOneToManyList()
{
}
/// <summary>
/// 设置最大缓存数量
/// </summary>
/// <param name="recyclingLimit">
/// 1:防止数据量过大、所以超过recyclingLimit的数据还是走GC.
/// 2:设置成0不控制数量全部缓存
/// </param>
public SortedOneToManyList(int recyclingLimit = 0)
{
_recyclingLimit = recyclingLimit;
}
public bool Contains(TKey key, TValue value)
{
TryGetValue(key, out var list);
return list != null && list.Contains(value);
}
public void Add(TKey key, TValue value)
{
if (!TryGetValue(key, out var list))
{
list = Fetch();
list.Add(value);
base[key] = list;
return;
}
list.Add(value);
}
public TValue First(TKey key)
{
return !TryGetValue(key, out var list) ? default : list.FirstOrDefault();
}
public void RemoveValue(TKey key, TValue value)
{
if (!TryGetValue(key, out var list))
{
return;
}
list.Remove(value);
if (list.Count == 0)
{
RemoveKey(key);
}
}
public void RemoveKey(TKey key)
{
if (!TryGetValue(key, out var list))
{
return;
}
Remove(key);
Recycle(list);
}
private List<TValue> Fetch()
{
return _queue.Count <= 0 ? new List<TValue>() : _queue.Dequeue();
}
private void Recycle(List<TValue> list)
{
list.Clear();
if (_recyclingLimit != 0 && _queue.Count > _recyclingLimit)
{
return;
}
_queue.Enqueue(list);
}
protected new void Clear()
{
base.Clear();
_queue.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: db62c1998de4d5048bde5d5e09d6f284
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: