From 6bbe37cbb38cb9ba9257e09a2c14e8575fb2491f Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Mon, 8 Nov 2021 15:51:49 +0100 Subject: [PATCH 1/5] Update FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 7cb18b2..cb60047 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1,2 @@ github: Ellpeck +ko_fi: Ellpeck From 1deb8a9d893384eda4eb5e4c07aab17da117d011 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Mon, 29 Nov 2021 11:37:17 +0100 Subject: [PATCH 2/5] ensure coroutine handler instance thread safety --- Coroutine/CoroutineHandlerInstance.cs | 74 +++++++++++++++++---------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/Coroutine/CoroutineHandlerInstance.cs b/Coroutine/CoroutineHandlerInstance.cs index 6a0247c..ba15111 100644 --- a/Coroutine/CoroutineHandlerInstance.cs +++ b/Coroutine/CoroutineHandlerInstance.cs @@ -16,15 +16,26 @@ namespace Coroutine { private readonly HashSet outstandingEventCoroutines = new HashSet(); private readonly HashSet outstandingTickingCoroutines = new HashSet(); private readonly Stopwatch stopwatch = new Stopwatch(); + private readonly object lockObject = new object(); /// /// The amount of instances that are currently waiting for a tick (waiting for time to pass) /// - public int TickingCount => this.tickingCoroutines.Count; + public int TickingCount { + get { + lock (this.lockObject) + return this.tickingCoroutines.Count; + } + } /// /// The amount of instances that are currently waiting for an /// - public int EventCount => this.eventCoroutines.Sum(c => c.Value.Count); + public int EventCount { + get { + lock (this.lockObject) + return this.eventCoroutines.Sum(c => c.Value.Count); + } + } /// /// Starts the given coroutine, returning a object for management. @@ -47,8 +58,10 @@ namespace Coroutine { /// An active coroutine object representing this coroutine public ActiveCoroutine Start(IEnumerator coroutine, string name = "", int priority = 0) { var inst = new ActiveCoroutine(coroutine, name, priority, this.stopwatch); - if (inst.MoveNext()) - this.GetOutstandingCoroutines(inst.IsWaitingForEvent).Add(inst); + if (inst.MoveNext()) { + lock (this.lockObject) + this.GetOutstandingCoroutines(inst.IsWaitingForEvent).Add(inst); + } return inst; } @@ -70,16 +83,18 @@ namespace Coroutine { /// /// The amount of seconds that have passed since the last time this method was invoked public void Tick(double deltaSeconds) { - this.MoveOutstandingCoroutines(false); - this.tickingCoroutines.RemoveAll(c => { - if (c.Tick(deltaSeconds)) { - return true; - } else if (c.IsWaitingForEvent) { - this.outstandingEventCoroutines.Add(c); - return true; - } - return false; - }); + lock (this.lockObject) { + this.MoveOutstandingCoroutines(false); + this.tickingCoroutines.RemoveAll(c => { + if (c.Tick(deltaSeconds)) { + return true; + } else if (c.IsWaitingForEvent) { + this.outstandingEventCoroutines.Add(c); + return true; + } + return false; + }); + } } /// @@ -96,19 +111,21 @@ namespace Coroutine { /// /// The event to raise public void RaiseEvent(Event evt) { - this.MoveOutstandingCoroutines(true); - var coroutines = this.GetEventCoroutines(evt, false); - if (coroutines != null) { - for (var i = 0; i < coroutines.Count; i++) { - var c = coroutines[i]; - var tup = (c.Event, c); - if (this.eventCoroutinesToRemove.Contains(tup)) - continue; - if (c.OnEvent(evt)) { - this.eventCoroutinesToRemove.Add(tup); - } else if (!c.IsWaitingForEvent) { - this.eventCoroutinesToRemove.Add(tup); - this.outstandingTickingCoroutines.Add(c); + lock (this.lockObject) { + this.MoveOutstandingCoroutines(true); + var coroutines = this.GetEventCoroutines(evt, false); + if (coroutines != null) { + for (var i = 0; i < coroutines.Count; i++) { + var c = coroutines[i]; + var tup = (c.Event, c); + if (this.eventCoroutinesToRemove.Contains(tup)) + continue; + if (c.OnEvent(evt)) { + this.eventCoroutinesToRemove.Add(tup); + } else if (!c.IsWaitingForEvent) { + this.eventCoroutinesToRemove.Add(tup); + this.outstandingTickingCoroutines.Add(c); + } } } } @@ -119,7 +136,8 @@ namespace Coroutine { /// /// All active coroutines public IEnumerable GetActiveCoroutines() { - return this.tickingCoroutines.Concat(this.eventCoroutines.Values.SelectMany(c => c)); + lock (this.lockObject) + return this.tickingCoroutines.Concat(this.eventCoroutines.Values.SelectMany(c => c)); } private void MoveOutstandingCoroutines(bool evt) { From 4f09e640393641bcb8fb27c601f96c7dd4ea23f5 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Mon, 29 Nov 2021 11:43:48 +0100 Subject: [PATCH 3/5] update --- Coroutine/Coroutine.csproj | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Coroutine/Coroutine.csproj b/Coroutine/Coroutine.csproj index 1fbecdd..b819adc 100644 --- a/Coroutine/Coroutine.csproj +++ b/Coroutine/Coroutine.csproj @@ -13,7 +13,7 @@ MIT README.md Logo.png - 2.1.2 + 2.1.3 diff --git a/README.md b/README.md index 1315aae..c84e72f 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ There are two predefined ways to pause a coroutine: Additionally, Coroutine provides the following features: - Creation of custom events to wait for -- Creation of custom wait conditions - No multi-threading, which allows for any kind of process to be executed in a coroutine, including rendering +- Thread-safety, which allows for coroutines to be started from different threads # How to Use ## Setting up the CoroutineHandler From ffed3bcd456597387255d58b5afed54ca4ff66d6 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Wed, 14 Sep 2022 19:41:40 +0200 Subject: [PATCH 4/5] multi-target coroutine --- Coroutine/Coroutine.csproj | 6 +++++- Example/Example.csproj | 2 +- Tests/Tests.csproj | 16 ++++++++-------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Coroutine/Coroutine.csproj b/Coroutine/Coroutine.csproj index b819adc..2844664 100644 --- a/Coroutine/Coroutine.csproj +++ b/Coroutine/Coroutine.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + net45;netstandard2.0;net6.0 true @@ -20,4 +20,8 @@ + + + + \ No newline at end of file diff --git a/Example/Example.csproj b/Example/Example.csproj index 16e8042..79c4819 100644 --- a/Example/Example.csproj +++ b/Example/Example.csproj @@ -1,6 +1,6 @@  - netcoreapp3.1 + net6.0 Exe false diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 6746a39..00c9c3a 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,18 +1,18 @@ - netcoreapp3.1 + net6.0 false nunit - + - - - - - + + + + + - + From 8f3f960e57689b886ca98110a9c0c41b4909e3da Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Wed, 14 Sep 2022 19:42:33 +0200 Subject: [PATCH 5/5] 2.1.4 --- Coroutine/Coroutine.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Coroutine/Coroutine.csproj b/Coroutine/Coroutine.csproj index 2844664..dbb798b 100644 --- a/Coroutine/Coroutine.csproj +++ b/Coroutine/Coroutine.csproj @@ -13,7 +13,7 @@ MIT README.md Logo.png - 2.1.3 + 2.1.4