MoonTools.ECS/src/MessageStorage.cs

132 lines
2.7 KiB
C#
Raw Normal View History

2022-04-08 05:52:03 +00:00
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using MoonTools.ECS.Collections;
2022-03-07 07:17:05 +00:00
2022-04-08 05:52:03 +00:00
namespace MoonTools.ECS
2022-03-07 07:17:05 +00:00
{
2022-04-08 05:52:03 +00:00
internal abstract class MessageStorage
2022-03-07 07:17:05 +00:00
{
2022-04-08 05:52:03 +00:00
public abstract void Clear();
2022-03-07 07:17:05 +00:00
}
internal unsafe class MessageStorage<TMessage> : MessageStorage, IDisposable where TMessage : unmanaged
2022-03-07 07:17:05 +00:00
{
2022-04-08 05:52:03 +00:00
private int count = 0;
private int capacity = 128;
private TMessage* messages;
// duplicating storage here for fast iteration
private Dictionary<int, NativeArray<TMessage>> entityToMessages = new Dictionary<int, NativeArray<TMessage>>();
private bool disposed;
2022-04-08 05:52:03 +00:00
public MessageStorage()
2022-03-07 07:17:05 +00:00
{
messages = (TMessage*) NativeMemory.Alloc((nuint) (capacity * Unsafe.SizeOf<TMessage>()));
2022-03-07 07:17:05 +00:00
}
2022-04-08 05:52:03 +00:00
public void Add(in TMessage message)
2022-03-18 19:50:59 +00:00
{
2022-04-08 05:52:03 +00:00
if (count == capacity)
2022-03-18 19:50:59 +00:00
{
2022-04-08 05:52:03 +00:00
capacity *= 2;
messages = (TMessage*) NativeMemory.Realloc(messages, (nuint) (capacity * Unsafe.SizeOf<TMessage>()));
2022-03-18 19:50:59 +00:00
}
2022-04-08 05:52:03 +00:00
messages[count] = message;
count += 1;
}
2022-03-18 19:50:59 +00:00
public void Add(int entityID, in TMessage message)
{
if (!entityToMessages.ContainsKey(entityID))
2022-04-08 05:52:03 +00:00
{
entityToMessages.Add(entityID, new NativeArray<TMessage>());
2022-04-08 05:52:03 +00:00
}
entityToMessages[entityID].Add(message);
2022-03-07 07:17:05 +00:00
Add(message);
2022-04-08 05:52:03 +00:00
}
2022-03-07 07:17:05 +00:00
2022-04-08 05:52:03 +00:00
public bool Some()
{
return count > 0;
}
2022-03-16 07:33:38 +00:00
2022-04-08 05:52:03 +00:00
public ReadOnlySpan<TMessage> All()
{
return new ReadOnlySpan<TMessage>(messages, count);
2022-04-08 05:52:03 +00:00
}
public TMessage First()
{
return messages[0];
}
public ReverseSpanEnumerator<TMessage> WithEntity(int entityID)
2022-03-18 19:50:59 +00:00
{
if (entityToMessages.TryGetValue(entityID, out var messages))
{
return messages.GetEnumerator();
}
else
2022-03-18 19:50:59 +00:00
{
return ReverseSpanEnumerator<TMessage>.Empty;
2022-03-18 19:50:59 +00:00
}
}
2022-04-08 05:52:03 +00:00
public ref readonly TMessage FirstWithEntity(int entityID)
{
return ref entityToMessages[entityID][0];
2022-04-08 05:52:03 +00:00
}
2022-03-18 19:50:59 +00:00
2022-04-08 05:52:03 +00:00
public bool SomeWithEntity(int entityID)
{
return entityToMessages.ContainsKey(entityID) && entityToMessages[entityID].Count > 0;
2022-04-08 05:52:03 +00:00
}
2022-03-18 19:50:59 +00:00
2022-04-08 05:52:03 +00:00
public override void Clear()
2022-03-18 19:50:59 +00:00
{
2022-04-08 05:52:03 +00:00
count = 0;
foreach (var set in entityToMessages.Values)
2022-04-08 05:52:03 +00:00
{
set.Clear();
}
2022-03-18 19:50:59 +00:00
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
Clear();
if (disposing)
{
foreach (var array in entityToMessages.Values)
{
array.Dispose();
}
}
NativeMemory.Free(messages);
messages = null;
disposed = true;
}
}
~MessageStorage()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: false);
}
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
2022-03-07 07:17:05 +00:00
}
}