Skip to content

Commit

Permalink
Merge pull request #150 from neoeinstein/patch-1
Browse files Browse the repository at this point in the history
Fix handling of canceled (unit) tasks
  • Loading branch information
neoeinstein committed Feb 19, 2017
2 parents 19afe49 + 263ee19 commit 2d548e9
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 12 deletions.
41 changes: 29 additions & 12 deletions Libs/Hopac.Core/External/Tasks.cs
Expand Up @@ -32,7 +32,11 @@ private sealed class State : Work {
}
internal override void DoWork(ref Worker wr) {
var yJ = this.yJ;
yJ.Do(yJ.xT.Result).DoJob(ref wr, yK);
var xT = yJ.xT;
if (TaskStatus.Faulted == xT.Status)
Handler.DoHandle(yK, ref wr, xT.Exception);
else
yJ.Do(yJ.xT.Result).DoJob(ref wr, yK);
}
internal void Ready() {
Worker.ContinueOnThisThread(sr, this);
Expand Down Expand Up @@ -73,10 +77,10 @@ private sealed class State : Work {
internal override void DoWork(ref Worker wr) {
var yJ = this.yJ;
var uT = yJ.uT;
if (TaskStatus.RanToCompletion == uT.Status)
yJ.Do().DoJob(ref wr, yK);
else
if (TaskStatus.Faulted == uT.Status)
Handler.DoHandle(yK, ref wr, uT.Exception);
else
yJ.Do().DoJob(ref wr, yK);
}
internal void Ready() {
Worker.ContinueOnThisThread(sr, this);
Expand Down Expand Up @@ -108,7 +112,11 @@ internal sealed class TaskToJobAwaiter<X> : Work {
xK.DoHandle(ref wr, e);
}
internal override void DoWork(ref Worker wr) {
xK.DoCont(ref wr, xT.Result);
var xT = this.xT;
if (TaskStatus.Faulted == xT.Status)
xK.DoHandle(ref wr, xT.Exception);
else
xK.DoCont(ref wr, xT.Result);
}
public void Ready() {
Worker.ContinueOnThisThread(this.sr, this);
Expand Down Expand Up @@ -146,10 +154,12 @@ internal sealed class TaskToJobAwaiter : Work {
}
internal override void DoWork(ref Worker wr) {
var uT = this.uT;
if (TaskStatus.RanToCompletion == uT.Status)
uK.DoWork(ref wr);
else
if (TaskStatus.Faulted == uT.Status)
uK.DoHandle(ref wr, uT.Exception);
else {
uT.Wait();
uK.DoWork(ref wr);
}
}
internal void Ready() {
Worker.ContinueOnThisThread(this.sr, this);
Expand Down Expand Up @@ -203,7 +213,11 @@ internal sealed class TaskToAltAwaiter<X> : Cont<Unit> {
cts.Dispose();
if (0 != picked)
goto Done;
xK.DoCont(ref wr, xT.Result);
var xT = this.xT;
if (TaskStatus.Faulted == xT.Status)
xK.DoHandle(ref wr, xT.Exception);
else
xK.DoCont(ref wr, xT.Result);
Done:
return;
}
Expand Down Expand Up @@ -291,10 +305,13 @@ internal sealed class TaskToAltAwaiter : Cont<Unit> {
cts.Dispose();
if (0 != picked)
goto Done;
if (TaskStatus.RanToCompletion == uT.Status)
uK.DoWork(ref wr);
else
var uT = this.uT;
if (TaskStatus.Faulted == uT.Status)
uK.DoHandle(ref wr, uT.Exception);
else {
uT.Wait();
uK.DoWork(ref wr);
}
Done:
return;
}
Expand Down
53 changes: 53 additions & 0 deletions Tests/AdHocTests/TaskTests.fs
Expand Up @@ -11,6 +11,7 @@ open System.Threading.Tasks
open RunTask

exception Ex
exception Ex2

let verify n c = printfn "%s %s" (if c then "Ok" else "FAILURE") n

Expand Down Expand Up @@ -46,6 +47,58 @@ let run () =
|> run
|> testExpected [Ex]

let cancelled = TaskCanceledException()

let tcs = TaskCompletionSource<int>()
do Job.fromTask ^ fun () -> tcs.SetCanceled() ; tcs.Task
|> Job.catch
|> run
|> testExpected [cancelled]

let tcs = TaskCompletionSource<int>()
do Job.fromUnitTask ^ fun () -> tcs.SetCanceled() ; tcs.Task :> Task
|> Job.catch
|> run
|> testExpected [cancelled]

let tcs = TaskCompletionSource<int>()
do Job.fromTask ^ fun () -> tcs.SetException(Ex) ; tcs.Task
|> Job.catch
|> run
|> testExpected [Ex]

let tcs1 = TaskCompletionSource<int>()
let tcs2 = TaskCompletionSource<int>()
do Job.fromTask ^ fun () -> tcs1.SetException(Ex) ; tcs1.Task
|> Job.bind ^ Job.liftTask ^ fun _ -> tcs2.SetException(Ex2) ; tcs2.Task
|> Job.catch
|> run
|> testExpected [Ex]

let tcs = TaskCompletionSource<int>()
do Job.fromUnitTask ^ fun () -> tcs.SetException(Ex) ; tcs.Task :> Task
|> Job.catch
|> run
|> testExpected [Ex]

let tcs1 = TaskCompletionSource<int>()
let tcs2 = TaskCompletionSource<int>()
do 23
|> Job.liftTask ^ fun _ -> tcs1.SetException(Ex) ; tcs1.Task
|> Job.bind ^ Job.liftTask ^ fun _ -> tcs2.SetCanceled() ; tcs2.Task
|> Job.catch
|> run
|> testExpected [Ex]

let tcs1 = TaskCompletionSource<int>()
let tcs2 = TaskCompletionSource<int>()
do 23
|> Job.liftTask ^ fun _ -> tcs1.SetCanceled() ; tcs1.Task
|> Job.bind ^ Job.liftTask ^ fun _ -> tcs2.SetException(Ex) ; tcs2.Task
|> Job.catch
|> run
|> testExpected [cancelled]

do delayAndRaise 50 Ex
<|> delayAndSet 203 ^ ref 1
|> Job.catch
Expand Down

0 comments on commit 2d548e9

Please sign in to comment.