rework ReadMessages to return a Span
continuous-integration/drone/push Build is passing Details

pull/3/head
Evan Hemsley 2020-03-22 13:41:55 -07:00
parent 67bc55e780
commit cdc68e46e5
9 changed files with 40 additions and 40 deletions

View File

@ -18,17 +18,17 @@ namespace Encompass
return _stores[typeof(TMessage)] as TypedMessageStore<TMessage>;
}
public void AddMessage<TMessage>(TMessage message) where TMessage : struct, IMessage
public void AddMessage<TMessage>(in TMessage message) where TMessage : struct, IMessage
{
Lookup<TMessage>().Add(message);
}
public void AddMessage<TMessage>(TMessage message, double time) where TMessage : struct, IMessage
public void AddMessage<TMessage>(in TMessage message, double time) where TMessage : struct, IMessage
{
Lookup<TMessage>().Add(message, time);
}
public void AddMessageIgnoringTimeDilation<TMessage>(TMessage message, double time) where TMessage : struct, IMessage
public void AddMessageIgnoringTimeDilation<TMessage>(in TMessage message, double time) where TMessage : struct, IMessage
{
Lookup<TMessage>().AddIgnoringTimeDilation(message, time);
}
@ -38,7 +38,7 @@ namespace Encompass
return Lookup<TMessage>().First();
}
public IEnumerable<TMessage> All<TMessage>() where TMessage : struct, IMessage
public Span<TMessage> All<TMessage>() where TMessage : struct, IMessage
{
return Lookup<TMessage>().All();
}

View File

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
namespace Encompass
@ -10,12 +11,13 @@ namespace Encompass
internal class TypedMessageStore<TMessage> : TypedMessageStore where TMessage : struct, IMessage
{
private readonly List<int> _indices = new List<int>();
// messages are placed in a contiguous region
// so we can return the collection as a Span
private int _nextIndex = 0;
private readonly TMessage[] _store = new TMessage[128];
private readonly List<(TMessage, double)> _delayedStore = new List<(TMessage, double)>(128);
private readonly List<(TMessage, double)> _delayedStoreIgnoringTimeDilation = new List<(TMessage, double)>(128);
private readonly Dictionary<int, HashSet<int>> _entityToIndices = new Dictionary<int, HashSet<int>>();
private readonly IDManager _idManager = new IDManager();
public override void ProcessDelayedMessages(double dilatedDelta, double realtimeDelta)
{
@ -56,8 +58,7 @@ namespace Encompass
public void Add(in TMessage message)
{
var index = _idManager.NextID();
_indices.Add(index);
var index = _nextIndex++;
_store[index] = message;
if (message is IHasEntity entityMessage)
{
@ -79,20 +80,17 @@ namespace Encompass
public TMessage First()
{
return _store[_indices[0]];
return _store[0];
}
public bool Any()
{
return _indices.Count > 0;
return _nextIndex != 0;
}
public IEnumerable<TMessage> All()
public Span<TMessage> All()
{
foreach (var index in _indices)
{
yield return _store[index];
}
return new Span<TMessage>(_store, 0, _nextIndex);
}
public IEnumerable<TMessage> WithEntity(int entityID)
@ -113,11 +111,7 @@ namespace Encompass
public override void Clear()
{
foreach (var index in _indices)
{
_idManager.Free(index);
}
_indices.Clear();
_nextIndex = 0;
foreach (var set in _entityToIndices.Values)
{
set.Clear();

View File

@ -529,7 +529,7 @@ namespace Encompass
/// <exception cref="Encompass.Exceptions.IllegalSendException">
/// Thrown when the Engine does not declare that it Sends the Message Type.
/// </exception>
protected void SendMessage<TMessage>(TMessage message) where TMessage : struct, IMessage
protected void SendMessage<TMessage>(in TMessage message) where TMessage : struct, IMessage
{
if (!SendTypes.Contains(typeof(TMessage)))
{
@ -543,7 +543,7 @@ namespace Encompass
/// Sends a message after the specified number of seconds, respecting time dilation.
/// </summary>
/// <param name="time">The time in seconds that will elapse before the message is sent.</param>
protected void SendMessage<TMessage>(TMessage message, double time) where TMessage : struct, IMessage
protected void SendMessage<TMessage>(in TMessage message, double time) where TMessage : struct, IMessage
{
_messageManager.AddMessage(message, time);
}
@ -552,7 +552,7 @@ namespace Encompass
/// Sends a message after the specified number of seconds, ignoring time dilation.
/// </summary>
/// <param name="time">The time in seconds that will elapse before the message is sent.</param>
protected void SendMessageIgnoringTimeDilation<TMessage>(TMessage message, double time) where TMessage : struct, IMessage
protected void SendMessageIgnoringTimeDilation<TMessage>(in TMessage message, double time) where TMessage : struct, IMessage
{
_messageManager.AddMessageIgnoringTimeDilation(message, time);
}
@ -563,7 +563,7 @@ namespace Encompass
/// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that it Receives the specified Message Type.
/// </exception>
protected IEnumerable<TMessage> ReadMessages<TMessage>() where TMessage : struct, IMessage
protected Span<TMessage> ReadMessages<TMessage>() where TMessage : struct, IMessage
{
CheckMessageRead<TMessage>();
return _messageManager.GetMessagesByType<TMessage>();

View File

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
namespace Encompass
@ -12,17 +13,17 @@ namespace Encompass
_timeManager = timeManager;
}
internal void AddMessage<TMessage>(TMessage message) where TMessage : struct, IMessage
internal void AddMessage<TMessage>(in TMessage message) where TMessage : struct, IMessage
{
_messageStore.AddMessage(message);
}
internal void AddMessage<TMessage>(TMessage message, double time) where TMessage : struct, IMessage
internal void AddMessage<TMessage>(in TMessage message, double time) where TMessage : struct, IMessage
{
_messageStore.AddMessage(message, time);
}
internal void AddMessageIgnoringTimeDilation<TMessage>(TMessage message, double time) where TMessage : struct, IMessage
internal void AddMessageIgnoringTimeDilation<TMessage>(in TMessage message, double time) where TMessage : struct, IMessage
{
_messageStore.AddMessageIgnoringTimeDilation(message, time);
}
@ -37,7 +38,7 @@ namespace Encompass
_messageStore.ProcessDelayedMessages(dt * _timeManager.TimeDilationFactor, dt);
}
internal IEnumerable<TMessage> GetMessagesByType<TMessage>() where TMessage : struct, IMessage
internal Span<TMessage> GetMessagesByType<TMessage>() where TMessage : struct, IMessage
{
return _messageStore.All<TMessage>();
}

View File

@ -58,7 +58,9 @@ namespace Encompass
CallGenericMethod(type, "SendMessage", 1, new object[] { Activator.CreateInstance(type) });
CallGenericMethod(type, "SendMessage", 2, new object[] { Activator.CreateInstance(type), 1 });
CallGenericMethod(type, "ReadMessage", null);
CallGenericMethod(type, "ReadMessages", null);
// can't reflect on methods that return a span...
//CallGenericMethod(type, "ReadMessages", null);
CallGenericMethod(type, "SomeMessage", null);
if (typeof(IHasEntity).IsAssignableFrom(type))
{

View File

@ -68,7 +68,7 @@ namespace Encompass
/// <summary>
/// Specifies that the given Message should be sent immediately on the first World Update.
/// </summary>
public void SendMessage<TMessage>(TMessage message) where TMessage : struct, IMessage
public void SendMessage<TMessage>(in TMessage message) where TMessage : struct, IMessage
{
_messageManager.AddMessage(message);
}
@ -76,7 +76,7 @@ namespace Encompass
/// <summary>
/// Specifies that the given Message should be sent after the specified number of seconds after the first World Update.
/// </summary>
public void SendMessage<TMessage>(TMessage message, double time) where TMessage : struct, IMessage
public void SendMessage<TMessage>(in TMessage message, double time) where TMessage : struct, IMessage
{
_messageManager.AddMessage<TMessage>(message, time);
}

View File

@ -45,7 +45,7 @@ namespace Tests
{
public override void Update(double dt)
{
foreach (var addComponentTestMessage in ReadMessages<AddComponentTestMessage>())
foreach (ref readonly var addComponentTestMessage in ReadMessages<AddComponentTestMessage>())
{
Assert.IsTrue(HasComponent<MockComponent>(addComponentTestMessage.entity));
ref readonly var gottenComponent = ref GetComponent<MockComponent>(addComponentTestMessage.entity);

View File

@ -20,7 +20,7 @@ namespace Tests
static List<MockComponent> resultComponents;
static MockComponent resultComponent;
static List<MockMessage> resultMessages = new List<MockMessage>();
static MockMessage[] resultMessages;
[Reads(typeof(MockComponent))]
public class ReadComponentsTestEngine : Engine
@ -279,7 +279,7 @@ namespace Tests
{
public override void Update(double dt)
{
resultMessages = this.ReadMessages<MockMessage>().ToList();
resultMessages = ReadMessages<MockMessage>().ToArray();
}
}
@ -308,14 +308,14 @@ namespace Tests
}
}
static IEnumerable<MockMessage> emptyReadMessagesResult;
static MockMessage[] emptyReadMessagesResult;
[Receives(typeof(MockMessage))]
class ReadMessagesWhenNoneExistEngine : Engine
{
public override void Update(double dt)
{
emptyReadMessagesResult = ReadMessages<MockMessage>();
emptyReadMessagesResult = ReadMessages<MockMessage>().ToArray();
}
}
@ -799,7 +799,7 @@ namespace Tests
[Test]
public void EngineSendMessageDelayed()
{
resultMessages.Clear();
Array.Clear(resultMessages, 0, resultMessages.Length);
var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new ActivateTimeDilationEngine());
@ -846,7 +846,7 @@ namespace Tests
[Test]
public void EngineSendMessageDelayedIgnoringTimeDilation()
{
resultMessages.Clear();
Array.Clear(resultMessages, 0, resultMessages.Length);
var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new ActivateTimeDilationEngine());

View File

@ -5,6 +5,7 @@ using System.Collections.Generic;
using Encompass.Exceptions;
using System.Linq;
using FluentAssertions;
using System;
namespace Tests
{
@ -479,20 +480,22 @@ namespace Tests
Assert.That(order.IndexOf(engineC), Is.LessThan(order.IndexOf(engineD)));
}
static List<AMessage> resultMessages = new List<AMessage>();
static AMessage[] resultMessages;
[Receives(typeof(AMessage))]
class ReadMessageEngine : Engine
{
public override void Update(double dt)
{
resultMessages = ReadMessages<AMessage>().ToList();
resultMessages = ReadMessages<AMessage>().ToArray();
}
}
[Test]
public void SendMessageDelayed()
{
resultMessages = Array.Empty<AMessage>();
var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new ReadMessageEngine());