From 708941ff0141ab4d0586943b580edd9c1185ad01 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Thu, 26 Mar 2020 01:35:37 +0100 Subject: [PATCH] synchronize coroutines to allow interaction from different threads --- Coroutine/CoroutineHandler.cs | 63 ++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/Coroutine/CoroutineHandler.cs b/Coroutine/CoroutineHandler.cs index 9e5e816..5686fd7 100644 --- a/Coroutine/CoroutineHandler.cs +++ b/Coroutine/CoroutineHandler.cs @@ -7,23 +7,28 @@ namespace Coroutine { private static readonly List TickingCoroutines = new List(); private static readonly List EventCoroutines = new List(); + private static readonly object Lock = new object(); public static ActiveCoroutine Start(IEnumerator coroutine) { - var inst = new ActiveCoroutine(coroutine); - var type = inst.GetCurrentType(); - if (type == WaitType.Tick) - TickingCoroutines.Add(inst); - else if (type == WaitType.Event) - EventCoroutines.Add(inst); - return inst; + lock (Lock) { + var inst = new ActiveCoroutine(coroutine); + var type = inst.GetCurrentType(); + if (type == WaitType.Tick) + TickingCoroutines.Add(inst); + else if (type == WaitType.Event) + EventCoroutines.Add(inst); + return inst; + } } public static bool Stop(ActiveCoroutine coroutine) { - if (TickingCoroutines.Remove(coroutine) || EventCoroutines.Remove(coroutine)) { - coroutine.Finish(true); - return true; + lock (Lock) { + if (TickingCoroutines.Remove(coroutine) || EventCoroutines.Remove(coroutine)) { + coroutine.Finish(true); + return true; + } + return false; } - return false; } public static void InvokeLater(IWait wait, Action action) { @@ -31,31 +36,37 @@ namespace Coroutine { } public static void Tick(double deltaSeconds) { - for (var i = TickingCoroutines.Count - 1; i >= 0; i--) { - var coroutine = TickingCoroutines[i]; - if (coroutine.Tick(deltaSeconds)) { - TickingCoroutines.RemoveAt(i); - } else if (coroutine.GetCurrentType() != WaitType.Tick) { - TickingCoroutines.RemoveAt(i); - EventCoroutines.Add(coroutine); + lock (Lock) { + for (var i = TickingCoroutines.Count - 1; i >= 0; i--) { + var coroutine = TickingCoroutines[i]; + if (coroutine.Tick(deltaSeconds)) { + TickingCoroutines.RemoveAt(i); + } else if (coroutine.GetCurrentType() != WaitType.Tick) { + TickingCoroutines.RemoveAt(i); + EventCoroutines.Add(coroutine); + } } } } public static void RaiseEvent(Event evt) { - for (var i = EventCoroutines.Count - 1; i >= 0; i--) { - var coroutine = EventCoroutines[i]; - if (coroutine.OnEvent(evt)) { - EventCoroutines.RemoveAt(i); - } else if (coroutine.GetCurrentType() != WaitType.Event) { - EventCoroutines.RemoveAt(i); - TickingCoroutines.Add(coroutine); + lock (Lock) { + for (var i = EventCoroutines.Count - 1; i >= 0; i--) { + var coroutine = EventCoroutines[i]; + if (coroutine.OnEvent(evt)) { + EventCoroutines.RemoveAt(i); + } else if (coroutine.GetCurrentType() != WaitType.Event) { + EventCoroutines.RemoveAt(i); + TickingCoroutines.Add(coroutine); + } } } } public static IEnumerable GetActiveCoroutines() { - return TickingCoroutines.Concat(EventCoroutines); + lock (Lock) { + return TickingCoroutines.Concat(EventCoroutines); + } } private static IEnumerator InvokeLaterImpl(IWait wait, Action action) {