2024-06-18 10:48:59 +08:00
|
|
|
using System;
|
2025-03-24 14:42:40 +08:00
|
|
|
using System.Buffers;
|
2024-06-18 10:48:59 +08:00
|
|
|
using System.Collections.Concurrent;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
2024-06-22 17:58:05 +08:00
|
|
|
using System.Runtime.CompilerServices;
|
2025-03-24 14:42:40 +08:00
|
|
|
using System.Runtime.InteropServices;
|
2024-06-22 17:58:05 +08:00
|
|
|
using System.Security.AccessControl;
|
2024-06-18 10:48:59 +08:00
|
|
|
using System.Threading;
|
2025-03-24 14:42:40 +08:00
|
|
|
using kcp2k;
|
2025-02-24 23:02:43 +08:00
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
using Microsoft.Extensions.Logging;
|
2025-03-24 14:42:40 +08:00
|
|
|
using Unity.Mathematics;
|
2024-06-18 10:48:59 +08:00
|
|
|
|
|
|
|
namespace BITKit.Entities
|
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
public static class EntitiesServiceExtensions
|
2024-06-18 10:48:59 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
internal static T GetRequiredServiceWithId<T>(this IServiceProvider serviceProvider, int id)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
return serviceProvider.GetRequiredService<T>();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-14 15:39:28 +08:00
|
|
|
public class EntitiesService : IEntitiesService, IDisposable
|
2025-03-24 14:42:40 +08:00
|
|
|
{
|
|
|
|
private static int _count;
|
|
|
|
|
|
|
|
private readonly ILogger<EntitiesService> _logger;
|
|
|
|
private readonly ITicker _ticker;
|
2025-03-09 13:38:23 +08:00
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
private readonly ConcurrentQueue<IEntity> _onAddQueue = new();
|
2025-04-14 15:39:28 +08:00
|
|
|
private readonly HashSet<IEntity> _addingEntities = new();
|
2025-03-24 14:42:40 +08:00
|
|
|
private readonly Dictionary<int, HashSet<int>> _typeCaches = new();
|
|
|
|
private readonly Dictionary<int, ConcurrentDictionary<int, object>> _typeInstances = new();
|
|
|
|
|
|
|
|
public EntitiesService(ILogger<EntitiesService> logger, ITicker ticker)
|
|
|
|
{
|
2025-03-09 13:38:23 +08:00
|
|
|
_logger = logger;
|
|
|
|
_ticker = ticker;
|
2025-03-24 14:42:40 +08:00
|
|
|
|
|
|
|
_pool = new(ObjectGenerator, null, 64);
|
|
|
|
|
|
|
|
_count++;
|
|
|
|
|
|
|
|
logger.LogInformation($"已创建EntitiesService,当前有:{_count}个实例");
|
|
|
|
|
|
|
|
_ticker?.Add(OnTick);
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
|
|
|
|
2025-03-09 13:38:23 +08:00
|
|
|
private void OnTick(float obj)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
while (_onAddQueue.TryDequeue(out var entity))
|
2025-03-09 13:38:23 +08:00
|
|
|
{
|
2025-04-14 15:39:28 +08:00
|
|
|
if(_addingEntities.Remove(entity) is false)continue;
|
2025-03-09 13:38:23 +08:00
|
|
|
OnAdd?.Invoke(entity);
|
2025-03-24 14:42:40 +08:00
|
|
|
MakeCache(entity);
|
|
|
|
}
|
2025-04-14 15:39:28 +08:00
|
|
|
_addingEntities.Clear();
|
2025-03-24 14:42:40 +08:00
|
|
|
}
|
2025-02-24 23:02:43 +08:00
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
private void MakeCache(IEntity entity)
|
|
|
|
{
|
|
|
|
foreach (var serviceDescriptor in entity.ServiceCollection)
|
|
|
|
{
|
|
|
|
var typeHash = serviceDescriptor.ServiceType.GetHashCode();
|
|
|
|
var hashSet = _typeCaches.GetOrCreate(typeHash);
|
|
|
|
hashSet.Add(entity.Id);
|
2025-03-09 13:38:23 +08:00
|
|
|
}
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2025-03-09 13:38:23 +08:00
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
private readonly Dictionary<int, IEntity> _entitiesInternal = new();
|
2024-06-18 10:48:59 +08:00
|
|
|
public event Action<IEntity> OnAdd;
|
|
|
|
public event Action<IEntity> OnRemove;
|
2025-03-24 14:42:40 +08:00
|
|
|
IReadOnlyDictionary<int, IEntity> IEntitiesService.Entities => _entitiesInternal;
|
|
|
|
private readonly Pool<HashSet<int>> _pool;
|
|
|
|
|
|
|
|
private HashSet<int> ObjectGenerator()
|
|
|
|
{
|
|
|
|
return new HashSet<int>(math.max(8192, _typeCaches.Count * 2));
|
|
|
|
}
|
|
|
|
|
2024-06-18 10:48:59 +08:00
|
|
|
public bool Register(IEntity entity)
|
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
if (!_entitiesInternal.TryAdd(entity.Id, entity)) return false;
|
|
|
|
if (_ticker is not null)
|
|
|
|
{
|
2025-04-14 15:39:28 +08:00
|
|
|
_addingEntities.Add(entity);
|
|
|
|
_onAddQueue.Enqueue(entity);
|
2025-03-24 14:42:40 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OnAdd?.Invoke(entity);
|
|
|
|
MakeCache(entity);
|
|
|
|
}
|
|
|
|
|
2024-06-18 10:48:59 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool UnRegister(IEntity entity)
|
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
if (!_entitiesInternal.TryRemove(entity.Id)) return false;
|
2025-04-14 15:39:28 +08:00
|
|
|
|
|
|
|
_addingEntities.Remove(entity);
|
2025-03-09 13:38:23 +08:00
|
|
|
|
|
|
|
foreach (var serviceDescriptor in entity.ServiceCollection)
|
|
|
|
{
|
|
|
|
var typeHash = serviceDescriptor.ServiceType.GetHashCode();
|
2025-03-24 14:42:40 +08:00
|
|
|
var hashSet = _typeCaches.GetOrCreate(typeHash);
|
2025-03-09 13:38:23 +08:00
|
|
|
hashSet.Remove(entity.Id);
|
|
|
|
}
|
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
_typeInstances.TryRemove(entity.Id);
|
|
|
|
|
2025-04-14 15:39:28 +08:00
|
|
|
OnRemove?.Invoke(entity);
|
2025-03-24 14:42:40 +08:00
|
|
|
|
2024-06-18 10:48:59 +08:00
|
|
|
return true;
|
|
|
|
}
|
2025-03-09 13:38:23 +08:00
|
|
|
|
2024-06-18 10:48:59 +08:00
|
|
|
public CancellationToken CancellationToken => _cancellationTokenSource.Token;
|
|
|
|
private readonly CancellationTokenSource _cancellationTokenSource = new();
|
2025-03-24 14:42:40 +08:00
|
|
|
|
2024-06-18 10:48:59 +08:00
|
|
|
public IEntity Get(int id)
|
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
return _entitiesInternal[id];
|
2024-06-18 10:48:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
public bool TryGetEntity(int id, out IEntity entity)
|
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
return _entitiesInternal.TryGetValue(id, out entity);
|
2024-06-18 10:48:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
public IEntity GetOrAdd(int id, Func<int, IEntity> factory)
|
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
if (_entitiesInternal.TryGetValue(id, out var current))
|
|
|
|
{
|
|
|
|
_entitiesInternal.TryAdd(id, current = factory.Invoke(id));
|
|
|
|
}
|
2024-06-18 10:48:59 +08:00
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
return current;
|
2024-06-18 10:48:59 +08:00
|
|
|
}
|
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
public Span<T> QueryComponents<T>() where T : class
|
2024-06-18 10:48:59 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
var pool = ArrayPool<T>.Shared;
|
|
|
|
|
|
|
|
var hashset = _typeCaches.GetOrCreate(typeof(T).GetHashCode());
|
|
|
|
|
|
|
|
var array = pool.Rent(hashset.Count);
|
|
|
|
var collection = _pool.Take();
|
|
|
|
collection.Clear();
|
|
|
|
|
|
|
|
collection.UnionWith(hashset);
|
|
|
|
|
|
|
|
var i = 0;
|
|
|
|
foreach (var id in collection)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
var instances = _typeInstances.GetOrCreate(id);
|
|
|
|
|
|
|
|
var h0 = typeof(T).GetHashCode();
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h0, out var v0) is false)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
instances[h0] = v0 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T>();
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2025-03-24 14:42:40 +08:00
|
|
|
|
|
|
|
array[i] = Unsafe.As<T>(v0);
|
|
|
|
i++;
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
try
|
|
|
|
{
|
|
|
|
return new Span<T>(array, 0, i);
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
pool.Return(array);
|
|
|
|
_pool.Return(collection);
|
|
|
|
}
|
2024-06-18 10:48:59 +08:00
|
|
|
}
|
2025-02-24 23:02:43 +08:00
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
public Span<(T, T1)> QueryComponents<T, T1>() where T : class where T1 : class
|
2024-06-18 10:48:59 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
var pool = ArrayPool<(T, T1)>.Shared;
|
|
|
|
|
|
|
|
var hashset = _typeCaches.GetOrCreate(typeof(T).GetHashCode());
|
|
|
|
var t1Set = _typeCaches.GetOrCreate(typeof(T1).GetHashCode());
|
|
|
|
|
|
|
|
var count = math.max(hashset.Count, t1Set.Count);
|
|
|
|
|
|
|
|
var array = pool.Rent(count);
|
|
|
|
var collection = _pool.Take();
|
|
|
|
collection.Clear();
|
|
|
|
|
|
|
|
collection.UnionWith(hashset);
|
|
|
|
collection.IntersectWith(t1Set);
|
|
|
|
|
|
|
|
var i = 0;
|
|
|
|
foreach (var id in collection)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
var instances = _typeInstances.GetOrCreate(id);
|
|
|
|
|
|
|
|
var h0 = typeof(T).GetHashCode();
|
|
|
|
var h1 = typeof(T1).GetHashCode();
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h0, out var v0) is false)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
instances[h0] = v0 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T>();
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2025-03-24 14:42:40 +08:00
|
|
|
|
|
|
|
if (instances.TryGetValue(h1, out var v1) is false)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
instances[h1] = v1 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T1>();
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2025-03-24 14:42:40 +08:00
|
|
|
|
|
|
|
array[i] = (Unsafe.As<T>(v0), Unsafe.As<T1>(v1));
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return new Span<(T, T1)>(array, 0, i);
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
pool.Return(array);
|
|
|
|
_pool.Return(collection);
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2024-06-18 10:48:59 +08:00
|
|
|
}
|
2024-06-22 17:58:05 +08:00
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
public Span<(T, T1, T2)> QueryComponents<T, T1, T2>() where T : class where T1 : class where T2 : class
|
2024-06-22 17:58:05 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
var pool = ArrayPool<(T, T1, T2)>.Shared;
|
|
|
|
|
|
|
|
var hashset = _typeCaches.GetOrCreate(typeof(T).GetHashCode());
|
|
|
|
var t1Set = _typeCaches.GetOrCreate(typeof(T1).GetHashCode());
|
|
|
|
var t2Set = _typeCaches.GetOrCreate(typeof(T2).GetHashCode());
|
|
|
|
|
|
|
|
var count = math.max(hashset.Count, math.max(t1Set.Count, t2Set.Count));
|
|
|
|
|
|
|
|
var array = pool.Rent(count);
|
|
|
|
var collection = _pool.Take();
|
|
|
|
collection.Clear();
|
|
|
|
|
|
|
|
collection.UnionWith(hashset);
|
|
|
|
collection.IntersectWith(t1Set);
|
|
|
|
collection.IntersectWith(t2Set);
|
|
|
|
|
|
|
|
var i = 0;
|
|
|
|
foreach (var id in collection)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
var instances = _typeInstances.GetOrCreate(id);
|
|
|
|
|
|
|
|
var h0 = typeof(T).GetHashCode();
|
|
|
|
var h1 = typeof(T1).GetHashCode();
|
|
|
|
var h2 = typeof(T2).GetHashCode();
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h0, out var v0) is false)
|
|
|
|
{
|
|
|
|
instances[h0] = v0 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h1, out var v1) is false)
|
|
|
|
{
|
|
|
|
instances[h1] = v1 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T1>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h2, out var v2) is false)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
instances[h2] = v2 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T2>();
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2025-03-24 14:42:40 +08:00
|
|
|
|
|
|
|
array[i] = (Unsafe.As<T>(v0), Unsafe.As<T1>(v1), Unsafe.As<T2>(v2));
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return new Span<(T, T1, T2)>(array, 0, i);
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
pool.Return(array);
|
|
|
|
_pool.Return(collection);
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2024-06-22 17:58:05 +08:00
|
|
|
}
|
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
public Span<(T, T1, T2, T3)> QueryComponents<T, T1, T2, T3>()
|
|
|
|
where T : class where T1 : class where T2 : class where T3 : class
|
2024-06-22 17:58:05 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
var pool = ArrayPool<(T, T1, T2, T3)>.Shared;
|
|
|
|
|
|
|
|
var hashset = _typeCaches.GetOrCreate(typeof(T).GetHashCode());
|
|
|
|
var t1Set = _typeCaches.GetOrCreate(typeof(T1).GetHashCode());
|
|
|
|
var t2Set = _typeCaches.GetOrCreate(typeof(T2).GetHashCode());
|
|
|
|
var t3Set = _typeCaches.GetOrCreate(typeof(T3).GetHashCode());
|
|
|
|
|
|
|
|
var count = math.max(hashset.Count, math.max(t1Set.Count, math.max(t2Set.Count, t3Set.Count)));
|
|
|
|
|
|
|
|
var array = pool.Rent(count);
|
|
|
|
var collection = _pool.Take();
|
|
|
|
collection.Clear();
|
|
|
|
|
|
|
|
collection.UnionWith(hashset);
|
|
|
|
collection.IntersectWith(t1Set);
|
|
|
|
collection.IntersectWith(t2Set);
|
|
|
|
collection.IntersectWith(t3Set);
|
|
|
|
|
|
|
|
var i = 0;
|
|
|
|
foreach (var id in collection)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
var instances = _typeInstances.GetOrCreate(id);
|
|
|
|
|
|
|
|
var h0 = typeof(T).GetHashCode();
|
|
|
|
var h1 = typeof(T1).GetHashCode();
|
|
|
|
var h2 = typeof(T2).GetHashCode();
|
|
|
|
var h3 = typeof(T3).GetHashCode();
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h0, out var v0) is false)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
instances[h0] = v0 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T>();
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2025-03-24 14:42:40 +08:00
|
|
|
|
|
|
|
if (instances.TryGetValue(h1, out var v1) is false)
|
|
|
|
{
|
|
|
|
instances[h1] = v1 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T1>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h2, out var v2) is false)
|
|
|
|
{
|
|
|
|
instances[h2] = v2 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T2>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h3, out var v3) is false)
|
|
|
|
{
|
|
|
|
instances[h3] = v3 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T3>();
|
|
|
|
}
|
|
|
|
|
|
|
|
array[i] = (Unsafe.As<T>(v0), Unsafe.As<T1>(v1), Unsafe.As<T2>(v2), Unsafe.As<T3>(v3));
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return new Span<(T, T1, T2, T3)>(array, 0, i);
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
pool.Return(array);
|
|
|
|
_pool.Return(collection);
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2024-06-22 17:58:05 +08:00
|
|
|
}
|
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
public Span<(T, T1, T2, T3, T4)> QueryComponents<T, T1, T2, T3, T4>() where T : class
|
|
|
|
where T1 : class
|
|
|
|
where T2 : class
|
|
|
|
where T3 : class
|
|
|
|
where T4 : class
|
2024-06-22 17:58:05 +08:00
|
|
|
{
|
2025-04-14 15:39:28 +08:00
|
|
|
var pool = ArrayPool<(T, T1, T2, T3,T4)>.Shared;
|
2025-03-24 14:42:40 +08:00
|
|
|
|
2025-04-14 15:39:28 +08:00
|
|
|
var hashset = _typeCaches.GetOrCreate(typeof(T).GetHashCode());
|
|
|
|
var t1Set = _typeCaches.GetOrCreate(typeof(T1).GetHashCode());
|
|
|
|
var t2Set = _typeCaches.GetOrCreate(typeof(T2).GetHashCode());
|
|
|
|
var t3Set = _typeCaches.GetOrCreate(typeof(T3).GetHashCode());
|
|
|
|
var t4Set = _typeCaches.GetOrCreate(typeof(T4).GetHashCode());
|
2025-04-05 09:49:01 +08:00
|
|
|
|
2025-04-14 15:39:28 +08:00
|
|
|
var count = math.max(hashset.Count, math.max(t1Set.Count, math.max(t2Set.Count,math.max(t3Set.Count,t4Set.Count))));
|
2025-04-05 09:49:01 +08:00
|
|
|
|
2025-04-14 15:39:28 +08:00
|
|
|
var array = pool.Rent(count);
|
|
|
|
var collection = _pool.Take();
|
|
|
|
collection.Clear();
|
2025-03-24 14:42:40 +08:00
|
|
|
|
2025-04-14 15:39:28 +08:00
|
|
|
collection.UnionWith(hashset);
|
|
|
|
collection.IntersectWith(t1Set);
|
|
|
|
collection.IntersectWith(t2Set);
|
|
|
|
collection.IntersectWith(t3Set);
|
2025-03-24 14:42:40 +08:00
|
|
|
|
|
|
|
var i = 0;
|
|
|
|
foreach (var id in collection)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
var instances = _typeInstances.GetOrCreate(id);
|
|
|
|
|
|
|
|
var h0 = typeof(T).GetHashCode();
|
|
|
|
var h1 = typeof(T1).GetHashCode();
|
|
|
|
var h2 = typeof(T2).GetHashCode();
|
|
|
|
var h3 = typeof(T3).GetHashCode();
|
|
|
|
var h4 = typeof(T4).GetHashCode();
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h0, out var v0) is false)
|
|
|
|
{
|
|
|
|
instances[h0] = v0 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h1, out var v1) is false)
|
|
|
|
{
|
|
|
|
instances[h1] = v1 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T1>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h2, out var v2) is false)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
instances[h2] = v2 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T2>();
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2025-03-24 14:42:40 +08:00
|
|
|
|
|
|
|
if (instances.TryGetValue(h3, out var v3) is false)
|
|
|
|
{
|
|
|
|
instances[h3] = v3 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T3>();
|
|
|
|
}
|
2025-04-14 15:39:28 +08:00
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
if (instances.TryGetValue(h4, out var v4) is false)
|
|
|
|
{
|
|
|
|
instances[h4] = v4 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T4>();
|
|
|
|
}
|
|
|
|
|
2025-04-14 15:39:28 +08:00
|
|
|
array[i] = (Unsafe.As<T>(v0), Unsafe.As<T1>(v1), Unsafe.As<T2>(v2), Unsafe.As<T3>(v3),Unsafe.As<T4>(v4));
|
2025-03-24 14:42:40 +08:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2025-04-14 15:39:28 +08:00
|
|
|
return new Span<(T, T1, T2, T3,T4)>(array, 0, i);
|
2025-03-24 14:42:40 +08:00
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
pool.Return(array);
|
2025-04-14 15:39:28 +08:00
|
|
|
_pool.Return(collection);
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2024-06-22 17:58:05 +08:00
|
|
|
}
|
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
public Span<(T, T1, T2, T3, T4, T5)> QueryComponents<T, T1, T2, T3, T4, T5>() where T : class
|
|
|
|
where T1 : class
|
|
|
|
where T2 : class
|
|
|
|
where T3 : class
|
|
|
|
where T4 : class
|
|
|
|
where T5 : class
|
2024-06-22 17:58:05 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
var pool = ArrayPool<(T, T1, T2, T3, T4, T5)>.Shared;
|
|
|
|
|
|
|
|
var hashset = _typeCaches.GetOrCreate(typeof(T).GetHashCode());
|
|
|
|
var t1Set = _typeCaches.GetOrCreate(typeof(T1).GetHashCode());
|
|
|
|
var t2Set = _typeCaches.GetOrCreate(typeof(T2).GetHashCode());
|
|
|
|
var t3Set = _typeCaches.GetOrCreate(typeof(T3).GetHashCode());
|
|
|
|
var t4Set = _typeCaches.GetOrCreate(typeof(T4).GetHashCode());
|
|
|
|
var t5Set = _typeCaches.GetOrCreate(typeof(T5).GetHashCode());
|
|
|
|
|
|
|
|
var count = math.max(hashset.Count,
|
|
|
|
math.max(t1Set.Count,
|
|
|
|
math.max(t2Set.Count, math.max(t3Set.Count, math.max(t4Set.Count, t5Set.Count)))));
|
|
|
|
|
|
|
|
var array = pool.Rent(count);
|
|
|
|
var collection = _pool.Take();
|
|
|
|
collection.Clear();
|
|
|
|
|
|
|
|
collection.UnionWith(hashset);
|
|
|
|
collection.IntersectWith(t1Set);
|
|
|
|
collection.IntersectWith(t2Set);
|
|
|
|
collection.IntersectWith(t3Set);
|
|
|
|
collection.IntersectWith(t4Set);
|
|
|
|
collection.IntersectWith(t5Set);
|
|
|
|
|
|
|
|
var i = 0;
|
|
|
|
foreach (var id in collection)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
var instances = _typeInstances.GetOrCreate(id);
|
|
|
|
|
|
|
|
var h0 = typeof(T).GetHashCode();
|
|
|
|
var h1 = typeof(T1).GetHashCode();
|
|
|
|
var h2 = typeof(T2).GetHashCode();
|
|
|
|
var h3 = typeof(T3).GetHashCode();
|
|
|
|
var h4 = typeof(T4).GetHashCode();
|
|
|
|
var h5 = typeof(T5).GetHashCode();
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h0, out var v0) is false)
|
|
|
|
{
|
|
|
|
instances[h0] = v0 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h1, out var v1) is false)
|
|
|
|
{
|
|
|
|
instances[h1] = v1 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T1>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h2, out var v2) is false)
|
|
|
|
{
|
|
|
|
instances[h2] = v2 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T2>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h3, out var v3) is false)
|
|
|
|
{
|
|
|
|
instances[h3] = v3 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T3>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h4, out var v4) is false)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
instances[h4] = v4 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T4>();
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2025-03-24 14:42:40 +08:00
|
|
|
|
|
|
|
if (instances.TryGetValue(h5, out var v5) is false)
|
|
|
|
{
|
|
|
|
instances[h5] = v5 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T5>();
|
|
|
|
}
|
|
|
|
|
|
|
|
array[i] = (Unsafe.As<T>(v0), Unsafe.As<T1>(v1), Unsafe.As<T2>(v2), Unsafe.As<T3>(v3),
|
|
|
|
Unsafe.As<T4>(v4), Unsafe.As<T5>(v5));
|
|
|
|
i++;
|
2025-04-05 09:49:01 +08:00
|
|
|
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
|
|
|
|
2025-04-05 09:49:01 +08:00
|
|
|
pool.Return(array);
|
2025-04-14 15:39:28 +08:00
|
|
|
_pool.Return(collection);
|
|
|
|
|
2025-04-05 09:49:01 +08:00
|
|
|
return new Span<(T, T1, T2, T3, T4, T5)>(array, 0, i);
|
2024-06-22 17:58:05 +08:00
|
|
|
}
|
|
|
|
|
2025-03-24 14:42:40 +08:00
|
|
|
public Span<(T, T1, T2, T3, T4, T5, T6)> QueryComponents<T, T1, T2, T3, T4, T5, T6>() where T : class
|
|
|
|
where T1 : class
|
|
|
|
where T2 : class
|
|
|
|
where T3 : class
|
|
|
|
where T4 : class
|
|
|
|
where T5 : class
|
|
|
|
where T6 : class
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
var pool = ArrayPool<(T, T1, T2, T3, T4, T5, T6)>.Shared;
|
|
|
|
|
|
|
|
var hashset = _typeCaches.GetOrCreate(typeof(T).GetHashCode());
|
|
|
|
var t1Set = _typeCaches.GetOrCreate(typeof(T1).GetHashCode());
|
|
|
|
var t2Set = _typeCaches.GetOrCreate(typeof(T2).GetHashCode());
|
|
|
|
var t3Set = _typeCaches.GetOrCreate(typeof(T3).GetHashCode());
|
|
|
|
var t4Set = _typeCaches.GetOrCreate(typeof(T4).GetHashCode());
|
|
|
|
var t5Set = _typeCaches.GetOrCreate(typeof(T5).GetHashCode());
|
|
|
|
var t6Set = _typeCaches.GetOrCreate(typeof(T6).GetHashCode());
|
|
|
|
|
|
|
|
var count = math.max(hashset.Count,
|
|
|
|
math.max(t1Set.Count,
|
|
|
|
math.max(t2Set.Count,
|
|
|
|
math.max(t3Set.Count, math.max(t4Set.Count, math.max(t5Set.Count, t6Set.Count))))));
|
|
|
|
|
|
|
|
var array = pool.Rent(count);
|
|
|
|
var collection = _pool.Take();
|
|
|
|
collection.Clear();
|
|
|
|
|
|
|
|
collection.UnionWith(hashset);
|
|
|
|
collection.IntersectWith(t1Set);
|
|
|
|
collection.IntersectWith(t2Set);
|
|
|
|
collection.IntersectWith(t3Set);
|
|
|
|
collection.IntersectWith(t4Set);
|
|
|
|
collection.IntersectWith(t5Set);
|
|
|
|
collection.IntersectWith(t6Set);
|
|
|
|
|
|
|
|
var i = 0;
|
|
|
|
foreach (var id in collection)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
var instances = _typeInstances.GetOrCreate(id);
|
|
|
|
|
|
|
|
var h0 = typeof(T).GetHashCode();
|
|
|
|
var h1 = typeof(T1).GetHashCode();
|
|
|
|
var h2 = typeof(T2).GetHashCode();
|
|
|
|
var h3 = typeof(T3).GetHashCode();
|
|
|
|
var h4 = typeof(T4).GetHashCode();
|
|
|
|
var h5 = typeof(T5).GetHashCode();
|
|
|
|
var h6 = typeof(T6).GetHashCode();
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h0, out var v0) is false)
|
|
|
|
{
|
|
|
|
instances[h0] = v0 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h1, out var v1) is false)
|
|
|
|
{
|
|
|
|
instances[h1] = v1 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T1>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h2, out var v2) is false)
|
|
|
|
{
|
|
|
|
instances[h2] = v2 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T2>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h3, out var v3) is false)
|
|
|
|
{
|
|
|
|
instances[h3] = v3 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T3>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h4, out var v4) is false)
|
|
|
|
{
|
|
|
|
instances[h4] = v4 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T4>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h5, out var v5) is false)
|
|
|
|
{
|
|
|
|
instances[h5] = v5 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T5>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instances.TryGetValue(h6, out var v6) is false)
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
instances[h6] = v6 = _entitiesInternal[id].ServiceProvider.GetRequiredService<T6>();
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2025-03-24 14:42:40 +08:00
|
|
|
|
|
|
|
array[i] = (Unsafe.As<T>(v0), Unsafe.As<T1>(v1), Unsafe.As<T2>(v2), Unsafe.As<T3>(v3),
|
|
|
|
Unsafe.As<T4>(v4), Unsafe.As<T5>(v5), Unsafe.As<T6>(v6));
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return new Span<(T, T1, T2, T3, T4, T5, T6)>(array, 0, i);
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
pool.Return(array);
|
|
|
|
_pool.Return(collection);
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Dispose()
|
2024-06-22 17:58:05 +08:00
|
|
|
{
|
2025-02-24 23:02:43 +08:00
|
|
|
_count--;
|
|
|
|
if (_count <= 0)
|
|
|
|
{
|
2025-03-24 14:42:40 +08:00
|
|
|
_entitiesInternal.Clear();
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
2025-03-24 14:42:40 +08:00
|
|
|
|
2025-02-24 23:02:43 +08:00
|
|
|
_logger.LogInformation($"已释放,还剩{_count}个实例");
|
2025-03-24 14:42:40 +08:00
|
|
|
|
2025-02-24 23:02:43 +08:00
|
|
|
_cancellationTokenSource?.Dispose();
|
2025-03-24 14:42:40 +08:00
|
|
|
|
|
|
|
_ticker?.Remove(OnTick);
|
2024-06-22 17:58:05 +08:00
|
|
|
}
|
2024-06-18 10:48:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|