mirror of
https://github.com/Ellpeck/Coroutine.git
synced 2024-11-22 05:43:29 +01:00
increase performance and scalability by storing event coroutines linked to their event
This commit is contained in:
parent
548e07f19f
commit
501d744326
6 changed files with 63 additions and 69 deletions
|
@ -13,6 +13,9 @@ namespace Coroutine {
|
||||||
private readonly Stopwatch stopwatch;
|
private readonly Stopwatch stopwatch;
|
||||||
private Wait current;
|
private Wait current;
|
||||||
|
|
||||||
|
internal Event Event => this.current.Event;
|
||||||
|
internal bool IsWaitingForEvent => this.Event != null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This property stores whether or not this active coroutine is finished.
|
/// This property stores whether or not this active coroutine is finished.
|
||||||
/// A coroutine is finished if all of its waits have passed, or if it <see cref="WasCanceled"/>.
|
/// A coroutine is finished if all of its waits have passed, or if it <see cref="WasCanceled"/>.
|
||||||
|
@ -79,18 +82,14 @@ namespace Coroutine {
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool Tick(double deltaSeconds) {
|
internal bool Tick(double deltaSeconds) {
|
||||||
if (!this.WasCanceled) {
|
if (!this.WasCanceled && this.current.Tick(deltaSeconds))
|
||||||
if (this.current.Tick(deltaSeconds))
|
|
||||||
this.MoveNext();
|
this.MoveNext();
|
||||||
}
|
|
||||||
return this.IsFinished;
|
return this.IsFinished;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool OnEvent(Event evt) {
|
internal bool OnEvent(Event evt) {
|
||||||
if (!this.WasCanceled) {
|
if (!this.WasCanceled && Equals(this.current.Event, evt))
|
||||||
if (this.current.OnEvent(evt))
|
|
||||||
this.MoveNext();
|
this.MoveNext();
|
||||||
}
|
|
||||||
return this.IsFinished;
|
return this.IsFinished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,10 +111,6 @@ namespace Coroutine {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool IsWaitingForEvent() {
|
|
||||||
return this.current.IsWaitingForEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A delegate method used by <see cref="ActiveCoroutine.OnFinished"/>.
|
/// A delegate method used by <see cref="ActiveCoroutine.OnFinished"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -11,9 +11,9 @@ namespace Coroutine {
|
||||||
public class CoroutineHandlerInstance {
|
public class CoroutineHandlerInstance {
|
||||||
|
|
||||||
private readonly List<ActiveCoroutine> tickingCoroutines = new List<ActiveCoroutine>();
|
private readonly List<ActiveCoroutine> tickingCoroutines = new List<ActiveCoroutine>();
|
||||||
private readonly List<ActiveCoroutine> eventCoroutines = new List<ActiveCoroutine>();
|
private readonly Dictionary<Event, List<ActiveCoroutine>> eventCoroutines = new Dictionary<Event, List<ActiveCoroutine>>();
|
||||||
|
private readonly Queue<ActiveCoroutine> eventCoroutinesToRemove = new Queue<ActiveCoroutine>();
|
||||||
private readonly Queue<ActiveCoroutine> outstandingCoroutines = new Queue<ActiveCoroutine>();
|
private readonly Queue<ActiveCoroutine> outstandingCoroutines = new Queue<ActiveCoroutine>();
|
||||||
private readonly ISet<int> eventCoroutinesToRemove = new HashSet<int>();
|
|
||||||
private readonly Stopwatch stopwatch = new Stopwatch();
|
private readonly Stopwatch stopwatch = new Stopwatch();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -23,7 +23,7 @@ namespace Coroutine {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The amount of <see cref="ActiveCoroutine"/> instances that are currently waiting for an <see cref="Event"/>
|
/// The amount of <see cref="ActiveCoroutine"/> instances that are currently waiting for an <see cref="Event"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int EventCount => this.eventCoroutines.Count;
|
public int EventCount => this.eventCoroutines.Sum(c => c.Value.Count);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Starts the given coroutine, returning a <see cref="ActiveCoroutine"/> object for management.
|
/// Starts the given coroutine, returning a <see cref="ActiveCoroutine"/> object for management.
|
||||||
|
@ -66,7 +66,6 @@ namespace Coroutine {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ticks this coroutine handler, causing all time-based <see cref="Wait"/>s to be ticked.
|
/// Ticks this coroutine handler, causing all time-based <see cref="Wait"/>s to be ticked.
|
||||||
/// Note that this method needs to be called even if only event-based coroutines are used.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="deltaSeconds">The amount of seconds that have passed since the last time this method was invoked</param>
|
/// <param name="deltaSeconds">The amount of seconds that have passed since the last time this method was invoked</param>
|
||||||
public void Tick(double deltaSeconds) {
|
public void Tick(double deltaSeconds) {
|
||||||
|
@ -74,7 +73,7 @@ namespace Coroutine {
|
||||||
this.tickingCoroutines.RemoveAll(c => {
|
this.tickingCoroutines.RemoveAll(c => {
|
||||||
if (c.Tick(deltaSeconds)) {
|
if (c.Tick(deltaSeconds)) {
|
||||||
return true;
|
return true;
|
||||||
} else if (c.IsWaitingForEvent()) {
|
} else if (c.IsWaitingForEvent) {
|
||||||
this.outstandingCoroutines.Enqueue(c);
|
this.outstandingCoroutines.Enqueue(c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -96,15 +95,19 @@ namespace Coroutine {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="evt">The event to raise</param>
|
/// <param name="evt">The event to raise</param>
|
||||||
public void RaiseEvent(Event evt) {
|
public void RaiseEvent(Event evt) {
|
||||||
for (var i = 0; i < this.eventCoroutines.Count; i++) {
|
this.MoveOutstandingCoroutines();
|
||||||
if (this.eventCoroutinesToRemove.Contains(i))
|
var coroutines = this.GetEventCoroutines(evt, 0);
|
||||||
|
if (coroutines != null) {
|
||||||
|
for (var i = 0; i < coroutines.Count; i++) {
|
||||||
|
var c = coroutines[i];
|
||||||
|
if (this.eventCoroutinesToRemove.Contains(c))
|
||||||
continue;
|
continue;
|
||||||
var c = this.eventCoroutines[i];
|
|
||||||
if (c.OnEvent(evt)) {
|
if (c.OnEvent(evt)) {
|
||||||
this.eventCoroutinesToRemove.Add(i);
|
this.eventCoroutinesToRemove.Enqueue(c);
|
||||||
} else if (!c.IsWaitingForEvent()) {
|
} else if (!c.IsWaitingForEvent) {
|
||||||
this.outstandingCoroutines.Enqueue(c);
|
this.outstandingCoroutines.Enqueue(c);
|
||||||
this.eventCoroutinesToRemove.Add(i);
|
this.eventCoroutinesToRemove.Enqueue(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,22 +117,32 @@ namespace Coroutine {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>All active coroutines</returns>
|
/// <returns>All active coroutines</returns>
|
||||||
public IEnumerable<ActiveCoroutine> GetActiveCoroutines() {
|
public IEnumerable<ActiveCoroutine> GetActiveCoroutines() {
|
||||||
return this.tickingCoroutines.Concat(this.eventCoroutines);
|
return this.tickingCoroutines.Concat(this.eventCoroutines.Values.SelectMany(c => c));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MoveOutstandingCoroutines() {
|
private void MoveOutstandingCoroutines() {
|
||||||
var i = 0;
|
while (this.eventCoroutinesToRemove.Count > 0) {
|
||||||
this.eventCoroutines.RemoveAll(c => this.eventCoroutinesToRemove.Contains(i++));
|
var c = this.eventCoroutinesToRemove.Peek();
|
||||||
this.eventCoroutinesToRemove.Clear();
|
this.GetEventCoroutines(c.Event, 0).Remove(c);
|
||||||
|
this.eventCoroutinesToRemove.Dequeue();
|
||||||
|
}
|
||||||
while (this.outstandingCoroutines.Count > 0) {
|
while (this.outstandingCoroutines.Count > 0) {
|
||||||
var coroutine = this.outstandingCoroutines.Dequeue();
|
var coroutine = this.outstandingCoroutines.Peek();
|
||||||
var list = coroutine.IsWaitingForEvent() ? this.eventCoroutines : this.tickingCoroutines;
|
var list = coroutine.IsWaitingForEvent ? this.GetEventCoroutines(coroutine.Event, 1) : this.tickingCoroutines;
|
||||||
var position = list.BinarySearch(coroutine);
|
var position = list.BinarySearch(coroutine);
|
||||||
list.Insert(position < 0 ? ~position : position, coroutine);
|
list.Insert(position < 0 ? ~position : position, coroutine);
|
||||||
|
this.outstandingCoroutines.Dequeue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<ActiveCoroutine> GetEventCoroutines(Event evt, int capacity) {
|
||||||
|
if (!this.eventCoroutines.TryGetValue(evt, out var ret) && capacity > 0) {
|
||||||
|
ret = new List<ActiveCoroutine>(capacity);
|
||||||
|
this.eventCoroutines.Add(evt, ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
private static IEnumerator<Wait> InvokeLaterImpl(Wait wait, Action action) {
|
private static IEnumerator<Wait> InvokeLaterImpl(Wait wait, Action action) {
|
||||||
yield return wait;
|
yield return wait;
|
||||||
action();
|
action();
|
||||||
|
|
|
@ -2,19 +2,19 @@ using System;
|
||||||
|
|
||||||
namespace Coroutine {
|
namespace Coroutine {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents either an amount of time, or an <see cref="Event"/> that is being waited for by an <see cref="ActiveCoroutine"/>.
|
/// Represents either an amount of time, or an <see cref="Coroutine.Event"/> that is being waited for by an <see cref="ActiveCoroutine"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct Wait {
|
public struct Wait {
|
||||||
|
|
||||||
private readonly Event evt;
|
internal readonly Event Event;
|
||||||
private double seconds;
|
private double seconds;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new wait that waits for the given <see cref="Event"/>.
|
/// Creates a new wait that waits for the given <see cref="Coroutine.Event"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="evt">The event to wait for</param>
|
/// <param name="evt">The event to wait for</param>
|
||||||
public Wait(Event evt) {
|
public Wait(Event evt) {
|
||||||
this.evt = evt;
|
this.Event = evt;
|
||||||
this.seconds = 0;
|
this.seconds = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ namespace Coroutine {
|
||||||
/// <param name="seconds">The amount of seconds to wait for</param>
|
/// <param name="seconds">The amount of seconds to wait for</param>
|
||||||
public Wait(double seconds) {
|
public Wait(double seconds) {
|
||||||
this.seconds = seconds;
|
this.seconds = seconds;
|
||||||
this.evt = null;
|
this.Event = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -40,13 +40,5 @@ namespace Coroutine {
|
||||||
return this.seconds <= 0;
|
return this.seconds <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool OnEvent(Event evt) {
|
|
||||||
return Equals(evt, this.evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal bool IsWaitingForEvent() {
|
|
||||||
return this.evt != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@ namespace Example {
|
||||||
|
|
||||||
CoroutineHandler.Start(EmptyCoroutine());
|
CoroutineHandler.Start(EmptyCoroutine());
|
||||||
|
|
||||||
CoroutineHandler.InvokeLater(new Wait(10), () => {
|
CoroutineHandler.InvokeLater(new Wait(5), () => {
|
||||||
Console.WriteLine("Raising test event");
|
Console.WriteLine("Raising test event");
|
||||||
CoroutineHandler.RaiseEvent(TestEvent);
|
CoroutineHandler.RaiseEvent(TestEvent);
|
||||||
});
|
});
|
||||||
|
|
|
@ -66,7 +66,5 @@ To actually cause the event to be raised, causing all currently waiting coroutin
|
||||||
CoroutineHandler.RaiseEvent(TestEvent);
|
CoroutineHandler.RaiseEvent(TestEvent);
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that, since `Tick` is an important lifecycle method, it has to be [called continuously](#Setting-up-the-CoroutineHandler) even if only event-based coroutines are used.
|
|
||||||
|
|
||||||
## Additional Examples
|
## Additional Examples
|
||||||
For additional examples, take a look at the [Example class](https://github.com/Ellpeck/Coroutine/blob/master/Example/Example.cs).
|
For additional examples, take a look at the [Example class](https://github.com/Ellpeck/Coroutine/blob/master/Example/Example.cs).
|
|
@ -21,7 +21,7 @@ namespace Tests {
|
||||||
Assert.AreEqual(string.Empty, cr.Name, "Incorrect default name found");
|
Assert.AreEqual(string.Empty, cr.Name, "Incorrect default name found");
|
||||||
Assert.AreEqual(0, cr.Priority, "Default priority is not minimum");
|
Assert.AreEqual(0, cr.Priority, "Default priority is not minimum");
|
||||||
for (var i = 0; i < 5; i++)
|
for (var i = 0; i < 5; i++)
|
||||||
SimulateTime(1);
|
CoroutineHandler.Tick(1);
|
||||||
Assert.AreEqual(2, counter, "instruction after yield is not executed.");
|
Assert.AreEqual(2, counter, "instruction after yield is not executed.");
|
||||||
Assert.AreEqual(true, cr.IsFinished, "Incorrect IsFinished value.");
|
Assert.AreEqual(true, cr.IsFinished, "Incorrect IsFinished value.");
|
||||||
Assert.AreEqual(false, cr.WasCanceled, "Incorrect IsCanceled value.");
|
Assert.AreEqual(false, cr.WasCanceled, "Incorrect IsCanceled value.");
|
||||||
|
@ -49,7 +49,7 @@ namespace Tests {
|
||||||
cr[0] = CoroutineHandler.Start(OnTimeTickNeverReturnYield());
|
cr[0] = CoroutineHandler.Start(OnTimeTickNeverReturnYield());
|
||||||
cr[1] = CoroutineHandler.Start(OnTimeTickYieldBreak());
|
cr[1] = CoroutineHandler.Start(OnTimeTickYieldBreak());
|
||||||
for (var i = 0; i < 5; i++)
|
for (var i = 0; i < 5; i++)
|
||||||
SimulateTime(1);
|
CoroutineHandler.Tick(1);
|
||||||
|
|
||||||
Assert.AreEqual(3, counter, "Incorrect counter value.");
|
Assert.AreEqual(3, counter, "Incorrect counter value.");
|
||||||
for (var i = 0; i < cr.Length; i++) {
|
for (var i = 0; i < cr.Length; i++) {
|
||||||
|
@ -71,7 +71,7 @@ namespace Tests {
|
||||||
|
|
||||||
var cr = CoroutineHandler.Start(OnTimeTickYieldDefault());
|
var cr = CoroutineHandler.Start(OnTimeTickYieldDefault());
|
||||||
for (var i = 0; i < 5; i++)
|
for (var i = 0; i < 5; i++)
|
||||||
SimulateTime(1);
|
CoroutineHandler.Tick(1);
|
||||||
|
|
||||||
Assert.AreEqual(2, counter, "Incorrect counter value.");
|
Assert.AreEqual(2, counter, "Incorrect counter value.");
|
||||||
Assert.AreEqual(true, cr.IsFinished, "Incorrect IsFinished value.");
|
Assert.AreEqual(true, cr.IsFinished, "Incorrect IsFinished value.");
|
||||||
|
@ -97,7 +97,7 @@ namespace Tests {
|
||||||
var cr = CoroutineHandler.Start(OnTimerTickInfinite());
|
var cr = CoroutineHandler.Start(OnTimerTickInfinite());
|
||||||
cr.OnFinished += SetCounterToUnreachableValue;
|
cr.OnFinished += SetCounterToUnreachableValue;
|
||||||
for (var i = 0; i < 50; i++)
|
for (var i = 0; i < 50; i++)
|
||||||
SimulateTime(1);
|
CoroutineHandler.Tick(1);
|
||||||
|
|
||||||
Assert.AreEqual(51, counter, "Incorrect counter value.");
|
Assert.AreEqual(51, counter, "Incorrect counter value.");
|
||||||
Assert.AreEqual(false, cr.IsFinished, "Incorrect IsFinished value.");
|
Assert.AreEqual(false, cr.IsFinished, "Incorrect IsFinished value.");
|
||||||
|
@ -126,7 +126,7 @@ namespace Tests {
|
||||||
|
|
||||||
var cr = CoroutineHandler.Start(OnTimeTick());
|
var cr = CoroutineHandler.Start(OnTimeTick());
|
||||||
cr.OnFinished += SetCounterToUnreachableValue;
|
cr.OnFinished += SetCounterToUnreachableValue;
|
||||||
SimulateTime(50);
|
CoroutineHandler.Tick(50);
|
||||||
Assert.AreEqual(-100, counter, "Incorrect counter value.");
|
Assert.AreEqual(-100, counter, "Incorrect counter value.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,22 +173,22 @@ namespace Tests {
|
||||||
Assert.AreEqual(0, counterGrandParent, "Grand Parent counter is invalid at time 0.");
|
Assert.AreEqual(0, counterGrandParent, "Grand Parent counter is invalid at time 0.");
|
||||||
Assert.AreEqual(0, counterParent, "Parent counter is invalid at time 0.");
|
Assert.AreEqual(0, counterParent, "Parent counter is invalid at time 0.");
|
||||||
Assert.AreEqual(0, counterChild, "Child counter is invalid at time 0.");
|
Assert.AreEqual(0, counterChild, "Child counter is invalid at time 0.");
|
||||||
SimulateTime(1);
|
CoroutineHandler.Tick(1);
|
||||||
Assert.AreEqual(1, counterAlwaysRunning, "Always running counter is invalid at time 1.");
|
Assert.AreEqual(1, counterAlwaysRunning, "Always running counter is invalid at time 1.");
|
||||||
Assert.AreEqual(1, counterGrandParent, "Grand Parent counter is invalid at time 1.");
|
Assert.AreEqual(1, counterGrandParent, "Grand Parent counter is invalid at time 1.");
|
||||||
Assert.AreEqual(0, counterParent, "Parent counter is invalid at time 1.");
|
Assert.AreEqual(0, counterParent, "Parent counter is invalid at time 1.");
|
||||||
Assert.AreEqual(0, counterChild, "Child counter is invalid at time 1.");
|
Assert.AreEqual(0, counterChild, "Child counter is invalid at time 1.");
|
||||||
SimulateTime(1);
|
CoroutineHandler.Tick(1);
|
||||||
Assert.AreEqual(2, counterAlwaysRunning, "Always running counter is invalid at time 2.");
|
Assert.AreEqual(2, counterAlwaysRunning, "Always running counter is invalid at time 2.");
|
||||||
Assert.AreEqual(1, counterGrandParent, "Grand Parent counter is invalid at time 2.");
|
Assert.AreEqual(1, counterGrandParent, "Grand Parent counter is invalid at time 2.");
|
||||||
Assert.AreEqual(1, counterParent, "Parent counter is invalid at time 2.");
|
Assert.AreEqual(1, counterParent, "Parent counter is invalid at time 2.");
|
||||||
Assert.AreEqual(0, counterChild, "Child counter is invalid at time 2.");
|
Assert.AreEqual(0, counterChild, "Child counter is invalid at time 2.");
|
||||||
SimulateTime(1);
|
CoroutineHandler.Tick(1);
|
||||||
Assert.AreEqual(3, counterAlwaysRunning, "Always running counter is invalid at time 3.");
|
Assert.AreEqual(3, counterAlwaysRunning, "Always running counter is invalid at time 3.");
|
||||||
Assert.AreEqual(1, counterGrandParent, "Grand Parent counter is invalid at time 3.");
|
Assert.AreEqual(1, counterGrandParent, "Grand Parent counter is invalid at time 3.");
|
||||||
Assert.AreEqual(1, counterParent, "Parent counter is invalid at time 3.");
|
Assert.AreEqual(1, counterParent, "Parent counter is invalid at time 3.");
|
||||||
Assert.AreEqual(1, counterChild, "Child counter is invalid at time 3.");
|
Assert.AreEqual(1, counterChild, "Child counter is invalid at time 3.");
|
||||||
SimulateTime(1);
|
CoroutineHandler.Tick(1);
|
||||||
Assert.AreEqual(4, counterAlwaysRunning, "Always running counter is invalid at time 4.");
|
Assert.AreEqual(4, counterAlwaysRunning, "Always running counter is invalid at time 4.");
|
||||||
Assert.AreEqual(1, counterGrandParent, "Grand Parent counter is invalid at time 4.");
|
Assert.AreEqual(1, counterGrandParent, "Grand Parent counter is invalid at time 4.");
|
||||||
Assert.AreEqual(1, counterParent, "Parent counter is invalid at time 4.");
|
Assert.AreEqual(1, counterParent, "Parent counter is invalid at time 4.");
|
||||||
|
@ -243,7 +243,7 @@ namespace Tests {
|
||||||
CoroutineHandler.Start(ShouldExecuteAfter());
|
CoroutineHandler.Start(ShouldExecuteAfter());
|
||||||
CoroutineHandler.Start(ShouldExecuteBefore0(), priority: highPriority);
|
CoroutineHandler.Start(ShouldExecuteBefore0(), priority: highPriority);
|
||||||
CoroutineHandler.Start(ShouldExecuteFinally(), priority: -1);
|
CoroutineHandler.Start(ShouldExecuteFinally(), priority: -1);
|
||||||
SimulateTime(10);
|
CoroutineHandler.Tick(10);
|
||||||
Assert.AreEqual(1, counterShouldExecuteAfter, $"ShouldExecuteAfter counter {counterShouldExecuteAfter} is invalid.");
|
Assert.AreEqual(1, counterShouldExecuteAfter, $"ShouldExecuteAfter counter {counterShouldExecuteAfter} is invalid.");
|
||||||
Assert.AreEqual(1, counterShouldExecuteFinally, $"ShouldExecuteFinally counter {counterShouldExecuteFinally} is invalid.");
|
Assert.AreEqual(1, counterShouldExecuteFinally, $"ShouldExecuteFinally counter {counterShouldExecuteFinally} is invalid.");
|
||||||
}
|
}
|
||||||
|
@ -270,10 +270,10 @@ namespace Tests {
|
||||||
|
|
||||||
CoroutineHandler.Start(IncrementCounter0Ever10Seconds());
|
CoroutineHandler.Start(IncrementCounter0Ever10Seconds());
|
||||||
CoroutineHandler.Start(IncrementCounter1Every5Seconds());
|
CoroutineHandler.Start(IncrementCounter1Every5Seconds());
|
||||||
SimulateTime(3);
|
CoroutineHandler.Tick(3);
|
||||||
Assert.AreEqual(0, counter0, "Incorrect counter0 value after 3 seconds.");
|
Assert.AreEqual(0, counter0, "Incorrect counter0 value after 3 seconds.");
|
||||||
Assert.AreEqual(0, counter1, "Incorrect counter1 value after 3 seconds.");
|
Assert.AreEqual(0, counter1, "Incorrect counter1 value after 3 seconds.");
|
||||||
SimulateTime(3);
|
CoroutineHandler.Tick(3);
|
||||||
Assert.AreEqual(0, counter0, "Incorrect counter0 value after 6 seconds.");
|
Assert.AreEqual(0, counter0, "Incorrect counter0 value after 6 seconds.");
|
||||||
Assert.AreEqual(1, counter1, "Incorrect counter1 value after 6 seconds.");
|
Assert.AreEqual(1, counter1, "Incorrect counter1 value after 6 seconds.");
|
||||||
|
|
||||||
|
@ -281,7 +281,7 @@ namespace Tests {
|
||||||
// increments 5 seconds after last yield. not 5 seconds since start.
|
// increments 5 seconds after last yield. not 5 seconds since start.
|
||||||
// So the when we send 3 seconds in the last SimulateTime,
|
// So the when we send 3 seconds in the last SimulateTime,
|
||||||
// the 3rd second was technically ignored.
|
// the 3rd second was technically ignored.
|
||||||
SimulateTime(5);
|
CoroutineHandler.Tick(5);
|
||||||
Assert.AreEqual(1, counter0, "Incorrect counter0 value after 10 seconds.");
|
Assert.AreEqual(1, counter0, "Incorrect counter0 value after 10 seconds.");
|
||||||
Assert.AreEqual(2, counter1, "Incorrect counter1 value after next 5 seconds.");
|
Assert.AreEqual(2, counter1, "Incorrect counter1 value after next 5 seconds.");
|
||||||
}
|
}
|
||||||
|
@ -293,9 +293,9 @@ namespace Tests {
|
||||||
counter++;
|
counter++;
|
||||||
}, "Bird");
|
}, "Bird");
|
||||||
|
|
||||||
SimulateTime(5);
|
CoroutineHandler.Tick(5);
|
||||||
Assert.AreEqual(0, counter, "Incorrect counter value after 5 seconds.");
|
Assert.AreEqual(0, counter, "Incorrect counter value after 5 seconds.");
|
||||||
SimulateTime(5);
|
CoroutineHandler.Tick(5);
|
||||||
Assert.AreEqual(1, counter, "Incorrect counter value after 10 seconds.");
|
Assert.AreEqual(1, counter, "Incorrect counter value after 10 seconds.");
|
||||||
Assert.AreEqual(true, cr.IsFinished, "Incorrect IsFinished value.");
|
Assert.AreEqual(true, cr.IsFinished, "Incorrect IsFinished value.");
|
||||||
Assert.AreEqual(false, cr.WasCanceled, "Incorrect IsCanceled value.");
|
Assert.AreEqual(false, cr.WasCanceled, "Incorrect IsCanceled value.");
|
||||||
|
@ -313,7 +313,7 @@ namespace Tests {
|
||||||
|
|
||||||
var cr = CoroutineHandler.Start(CoroutineTakesMax500Ms());
|
var cr = CoroutineHandler.Start(CoroutineTakesMax500Ms());
|
||||||
for (var i = 0; i < 5; i++)
|
for (var i = 0; i < 5; i++)
|
||||||
SimulateTime(50);
|
CoroutineHandler.Tick(50);
|
||||||
|
|
||||||
const int expected1 = 350;
|
const int expected1 = 350;
|
||||||
const float errorbar1 = 5 / 100f * expected1;
|
const float errorbar1 = 5 / 100f * expected1;
|
||||||
|
@ -328,9 +328,5 @@ namespace Tests {
|
||||||
Assert.IsTrue(gTc && lTd, $"Maximum Move Next Time {cr.MaxMoveNextTime.Milliseconds} is invalid.");
|
Assert.IsTrue(gTc && lTd, $"Maximum Move Next Time {cr.MaxMoveNextTime.Milliseconds} is invalid.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SimulateTime(double totalSeconds) {
|
|
||||||
CoroutineHandler.Tick(totalSeconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue