From cdc68e46e5d47072a4da8228aead93cb65242675 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 13:41:55 -0700 Subject: [PATCH] rework ReadMessages to return a Span --- encompass-cs/Collections/MessageStore.cs | 8 +++--- encompass-cs/Collections/TypedMessageStore.cs | 26 +++++++------------ encompass-cs/Engine.cs | 8 +++--- encompass-cs/MessageManager.cs | 9 ++++--- encompass-cs/UberEngine.cs | 4 ++- encompass-cs/WorldBuilder.cs | 4 +-- test/ComponentTest.cs | 2 +- test/EngineTest.cs | 12 ++++----- test/WorldBuilderTest.cs | 7 +++-- 9 files changed, 40 insertions(+), 40 deletions(-) diff --git a/encompass-cs/Collections/MessageStore.cs b/encompass-cs/Collections/MessageStore.cs index a966fe6..4d44657 100644 --- a/encompass-cs/Collections/MessageStore.cs +++ b/encompass-cs/Collections/MessageStore.cs @@ -18,17 +18,17 @@ namespace Encompass return _stores[typeof(TMessage)] as TypedMessageStore; } - public void AddMessage(TMessage message) where TMessage : struct, IMessage + public void AddMessage(in TMessage message) where TMessage : struct, IMessage { Lookup().Add(message); } - public void AddMessage(TMessage message, double time) where TMessage : struct, IMessage + public void AddMessage(in TMessage message, double time) where TMessage : struct, IMessage { Lookup().Add(message, time); } - public void AddMessageIgnoringTimeDilation(TMessage message, double time) where TMessage : struct, IMessage + public void AddMessageIgnoringTimeDilation(in TMessage message, double time) where TMessage : struct, IMessage { Lookup().AddIgnoringTimeDilation(message, time); } @@ -38,7 +38,7 @@ namespace Encompass return Lookup().First(); } - public IEnumerable All() where TMessage : struct, IMessage + public Span All() where TMessage : struct, IMessage { return Lookup().All(); } diff --git a/encompass-cs/Collections/TypedMessageStore.cs b/encompass-cs/Collections/TypedMessageStore.cs index f47e2da..b43f129 100644 --- a/encompass-cs/Collections/TypedMessageStore.cs +++ b/encompass-cs/Collections/TypedMessageStore.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace Encompass @@ -10,12 +11,13 @@ namespace Encompass internal class TypedMessageStore : TypedMessageStore where TMessage : struct, IMessage { - private readonly List _indices = new List(); + // 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> _entityToIndices = new Dictionary>(); - 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 All() + public Span All() { - foreach (var index in _indices) - { - yield return _store[index]; - } + return new Span(_store, 0, _nextIndex); } public IEnumerable 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(); diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index b5e6779..d98fe87 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -529,7 +529,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Sends the Message Type. /// - protected void SendMessage(TMessage message) where TMessage : struct, IMessage + protected void SendMessage(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. /// /// The time in seconds that will elapse before the message is sent. - protected void SendMessage(TMessage message, double time) where TMessage : struct, IMessage + protected void SendMessage(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. /// /// The time in seconds that will elapse before the message is sent. - protected void SendMessageIgnoringTimeDilation(TMessage message, double time) where TMessage : struct, IMessage + protected void SendMessageIgnoringTimeDilation(in TMessage message, double time) where TMessage : struct, IMessage { _messageManager.AddMessageIgnoringTimeDilation(message, time); } @@ -563,7 +563,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Receives the specified Message Type. /// - protected IEnumerable ReadMessages() where TMessage : struct, IMessage + protected Span ReadMessages() where TMessage : struct, IMessage { CheckMessageRead(); return _messageManager.GetMessagesByType(); diff --git a/encompass-cs/MessageManager.cs b/encompass-cs/MessageManager.cs index c662b6e..0ee4dc2 100644 --- a/encompass-cs/MessageManager.cs +++ b/encompass-cs/MessageManager.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace Encompass @@ -12,17 +13,17 @@ namespace Encompass _timeManager = timeManager; } - internal void AddMessage(TMessage message) where TMessage : struct, IMessage + internal void AddMessage(in TMessage message) where TMessage : struct, IMessage { _messageStore.AddMessage(message); } - internal void AddMessage(TMessage message, double time) where TMessage : struct, IMessage + internal void AddMessage(in TMessage message, double time) where TMessage : struct, IMessage { _messageStore.AddMessage(message, time); } - internal void AddMessageIgnoringTimeDilation(TMessage message, double time) where TMessage : struct, IMessage + internal void AddMessageIgnoringTimeDilation(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 GetMessagesByType() where TMessage : struct, IMessage + internal Span GetMessagesByType() where TMessage : struct, IMessage { return _messageStore.All(); } diff --git a/encompass-cs/UberEngine.cs b/encompass-cs/UberEngine.cs index c6f55b4..0003928 100644 --- a/encompass-cs/UberEngine.cs +++ b/encompass-cs/UberEngine.cs @@ -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)) { diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 68cb330..5da3d3a 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -68,7 +68,7 @@ namespace Encompass /// /// Specifies that the given Message should be sent immediately on the first World Update. /// - public void SendMessage(TMessage message) where TMessage : struct, IMessage + public void SendMessage(in TMessage message) where TMessage : struct, IMessage { _messageManager.AddMessage(message); } @@ -76,7 +76,7 @@ namespace Encompass /// /// Specifies that the given Message should be sent after the specified number of seconds after the first World Update. /// - public void SendMessage(TMessage message, double time) where TMessage : struct, IMessage + public void SendMessage(in TMessage message, double time) where TMessage : struct, IMessage { _messageManager.AddMessage(message, time); } diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs index b8826b2..e881f64 100644 --- a/test/ComponentTest.cs +++ b/test/ComponentTest.cs @@ -45,7 +45,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var addComponentTestMessage in ReadMessages()) + foreach (ref readonly var addComponentTestMessage in ReadMessages()) { Assert.IsTrue(HasComponent(addComponentTestMessage.entity)); ref readonly var gottenComponent = ref GetComponent(addComponentTestMessage.entity); diff --git a/test/EngineTest.cs b/test/EngineTest.cs index 208f455..dd4d7d6 100644 --- a/test/EngineTest.cs +++ b/test/EngineTest.cs @@ -20,7 +20,7 @@ namespace Tests static List resultComponents; static MockComponent resultComponent; - static List resultMessages = new List(); + 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().ToList(); + resultMessages = ReadMessages().ToArray(); } } @@ -308,14 +308,14 @@ namespace Tests } } - static IEnumerable emptyReadMessagesResult; + static MockMessage[] emptyReadMessagesResult; [Receives(typeof(MockMessage))] class ReadMessagesWhenNoneExistEngine : Engine { public override void Update(double dt) { - emptyReadMessagesResult = ReadMessages(); + emptyReadMessagesResult = ReadMessages().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()); diff --git a/test/WorldBuilderTest.cs b/test/WorldBuilderTest.cs index 9a705f2..68b333b 100644 --- a/test/WorldBuilderTest.cs +++ b/test/WorldBuilderTest.cs @@ -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 resultMessages = new List(); + static AMessage[] resultMessages; [Receives(typeof(AMessage))] class ReadMessageEngine : Engine { public override void Update(double dt) { - resultMessages = ReadMessages().ToList(); + resultMessages = ReadMessages().ToArray(); } } [Test] public void SendMessageDelayed() { + resultMessages = Array.Empty(); + var worldBuilder = new WorldBuilder(); worldBuilder.AddEngine(new ReadMessageEngine());