Skip to content

Commit cba1940

Browse files
committed
Add exception handling
Changes cancellation behaviour See #1
1 parent a07de3f commit cba1940

File tree

1 file changed

+49
-14
lines changed

1 file changed

+49
-14
lines changed

UnityAsync/Assets/UnityAsync/Continuation.cs

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Runtime.CompilerServices;
33
using System.Threading;
4+
using UnityEngine;
45
using Object = UnityEngine.Object;
56

67
namespace UnityAsync
@@ -18,33 +19,54 @@ public interface IContinuation
1819
/// <typeparam name="T">The type of <see cref="UnityAsync.IAwaitInstruction"/> to encapsulate.</typeparam>
1920
public struct Continuation<T> : IContinuation, INotifyCompletion where T : IAwaitInstruction
2021
{
22+
static Exception exception;
23+
2124
Object owner;
2225
CancellationToken cancellationToken;
2326

2427
/// <summary>
2528
/// Evaluate the encapsulated <see cref="UnityAsync.IAwaitInstruction"/>. If the instruction is finished, the
26-
/// continuation delegate is invoked and the method returns <code>true</code>. If the owner is destroyed or a
27-
/// cancellation was requested, the method will return true and will not invoke the continuation delegate.
28-
/// Otherwise, the method will return false, meaning the <see cref="UnityAsync.IAwaitInstruction"/> is not yet
29-
/// finished.
29+
/// continuation delegate is invoked and the method returns <code>true</code>. If the owner is destroyed, the
30+
/// method will return true without invoking the continuation delegate. If it was cancelled, an exception is
31+
/// is thrown when the continuation delegate is invoked. Otherwise, returns false (i.e. the instruction is not
32+
/// finished).
3033
/// </summary>
3134
/// <returns>
32-
/// <code>true</code> if the <see cref="UnityAsync.IAwaitInstruction"/> is finished or cancelled, otherwise
33-
/// false.
35+
/// <code>true</code> if the <see cref="UnityAsync.IAwaitInstruction"/> is finished, its owner destroyed,
36+
/// or has been cancelled, otherwise <code>false</code>.
3437
/// </returns>
3538
public bool Evaluate()
3639
{
37-
if(!owner || cancellationToken.IsCancellationRequested)
38-
return true;
39-
40-
if(instruction.IsCompleted())
40+
try
4141
{
42-
continuation();
42+
// if cancelled, throw exception
43+
cancellationToken.ThrowIfCancellationRequested();
4344

44-
return true;
45+
// if owner is destroyed, behaves like a UnityEngine.Coroutine, ie:
46+
// "With this object's death, the thread of prophecy is severed. Restore a saved game to restore the
47+
// weave of fate, or persist in the doomed world you have created."
48+
if(!owner)
49+
return true;
50+
51+
// if not completed, return false to put it back into a queue for next frame
52+
if(!instruction.IsCompleted())
53+
return false;
4554
}
55+
catch(Exception e)
56+
{
57+
// store exception in static field
58+
exception = e;
59+
60+
// exception is rethrown in GetResult, at start of continuation
61+
continuation();
4662

47-
return false;
63+
return true;
64+
}
65+
66+
// if we get here, it completed without exceptions and we can call continuation and be done with it
67+
continuation();
68+
69+
return true;
4870
}
4971

5072
public FrameScheduler Scheduler { get; private set; }
@@ -57,6 +79,7 @@ public Continuation(T inst)
5779
instruction = inst;
5880
continuation = null;
5981
owner = AsyncManager.Instance;
82+
exception = null;
6083
Scheduler = FrameScheduler.Update;
6184
}
6285

@@ -65,6 +88,7 @@ public Continuation(T inst, FrameScheduler scheduler)
6588
instruction = inst;
6689
continuation = null;
6790
owner = AsyncManager.Instance;
91+
exception = null;
6892
Scheduler = scheduler;
6993
}
7094

@@ -73,6 +97,7 @@ public Continuation(T inst, CancellationToken cancellationToken, FrameScheduler
7397
instruction = inst;
7498
continuation = null;
7599
owner = AsyncManager.Instance;
100+
exception = null;
76101
this.cancellationToken = cancellationToken;
77102
Scheduler = scheduler;
78103
}
@@ -82,6 +107,7 @@ public Continuation(T inst, Object owner, FrameScheduler scheduler)
82107
instruction = inst;
83108
continuation = null;
84109
this.owner = owner;
110+
exception = null;
85111
Scheduler = scheduler;
86112
}
87113

@@ -152,7 +178,16 @@ public Continuation<T> ConfigureAwait(CancellationToken cancellationToken)
152178
return this;
153179
}
154180

155-
public void GetResult() { }
181+
public void GetResult()
182+
{
183+
if(exception != null)
184+
{
185+
var e = exception;
186+
exception = null;
187+
188+
throw e;
189+
}
190+
}
156191

157192
[MethodImpl(MethodImplOptions.AggressiveInlining)]
158193
public Continuation<T> GetAwaiter() => this;

0 commit comments

Comments
 (0)