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 diff --git a/Coroutine/Coroutine.csproj b/Coroutine/Coroutine.csproj index 1fbecdd..dbb798b 100644 --- a/Coroutine/Coroutine.csproj +++ b/Coroutine/Coroutine.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + net45;netstandard2.0;net6.0 true @@ -13,11 +13,15 @@ MIT README.md Logo.png - 2.1.2 + 2.1.4 + + + + \ No newline at end of file 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) { 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/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 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 - + - - - - - + + + + + - +