Skip to content

Commit dd208ee

Browse files
committed
Fix
1 parent c6200cb commit dd208ee

File tree

1 file changed

+39
-37
lines changed

1 file changed

+39
-37
lines changed

src/FSharpPlus/Extensions/Task.fs

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -19,33 +19,47 @@ module Task =
1919
elif t.IsCanceled then Canceled
2020
else invalidOp "Internal error: The task is not yet completed."
2121

22+
23+
/// Creates a Task from a value
24+
let result (value: 'T) = Task.FromResult value
25+
26+
/// <summary>
27+
/// Raises an exception in the Task
28+
/// </summary>
29+
/// <param name="exn"></param>
30+
let raise<'T> (exn: exn) : Task<'T> =
31+
match exn with
32+
// AggregateException with multiple exceptions - use TCS
33+
| :? AggregateException as agg when agg.InnerExceptions.Count > 1 ->
34+
let tcs = TaskCompletionSource<'T>()
35+
tcs.SetException(agg.InnerExceptions)
36+
tcs.Task
37+
// Single non-aggregate exception - use optimized path
38+
// Single exception - use the optimized path
39+
| :? AggregateException as agg -> Task.FromException<'T> agg.InnerExceptions[0]
40+
| ex -> Task.FromException<'T> ex
41+
42+
let private canceledTokenSingleton = CancellationToken true
43+
let private canceled<'T> : Task<'T> = Task.FromCanceled<'T> canceledTokenSingleton
44+
45+
2246
/// <summary>Creates a task workflow from 'source' another, mapping its result with 'f'.</summary>
23-
let map (f: 'T -> 'U) (source: Task<'T>) : Task<'U> =
47+
let map (mapper: 'T -> 'U) (source: Task<'T>) : Task<'U> =
2448
let source = nullArgCheck (nameof source) source
2549

26-
if source.Status = TaskStatus.RanToCompletion then
27-
try Task.FromResult (f source.Result)
28-
with e ->
29-
let tcs = TaskCompletionSource<'U> ()
30-
tcs.SetException e
31-
tcs.Task
50+
if source.IsCompleted then
51+
match source with
52+
| Succeeded r -> try result (mapper r) with e -> raise<'U> e
53+
| Faulted exn -> raise<'U> exn
54+
| Canceled -> canceled<'U>
3255
else
3356
let tcs = TaskCompletionSource<'U> ()
34-
if source.Status = TaskStatus.Faulted then
35-
tcs.SetException (Unchecked.nonNull source.Exception).InnerExceptions
36-
tcs.Task
37-
elif source.Status = TaskStatus.Canceled then
38-
tcs.SetCanceled ()
39-
tcs.Task
40-
else
41-
let k = function
42-
| Canceled -> tcs.SetCanceled ()
43-
| Faulted e -> tcs.SetException e.InnerExceptions
44-
| Succeeded r ->
45-
try tcs.SetResult (f r)
46-
with e -> tcs.SetException e
47-
source.ContinueWith k |> ignore
48-
tcs.Task
57+
let k = function
58+
| Canceled -> tcs.SetCanceled ()
59+
| Faulted e -> tcs.SetException e.InnerExceptions
60+
| Succeeded r -> try tcs.SetResult (mapper r) with e -> tcs.SetException e
61+
source.ContinueWith k |> ignore
62+
tcs.Task
4963

5064
/// <summary>Creates a task workflow from two workflows 'x' and 'y', mapping its results with 'f'.</summary>
5165
/// <remarks>Workflows are run in sequence.</remarks>
@@ -408,13 +422,8 @@ module Task =
408422
ran <- true
409423
try
410424
let task = body ()
411-
let rec loop (task: Task<'T>) (compensation : unit -> unit) =
412-
match task.Status with
413-
| TaskStatus.RanToCompletion -> compensation (); task
414-
| TaskStatus.Faulted -> task.ContinueWith((fun (x:Task<'T>) -> compensation (); x)).Unwrap ()
415-
| TaskStatus.Canceled -> task
416-
| _ -> task.ContinueWith((fun (x:Task<'T>) -> (loop x compensation: Task<_>))).Unwrap ()
417-
loop task compensation
425+
if task.IsCompleted then compensation (); task
426+
else task.ContinueWith(fun (_: Task<'T>) -> compensation (); task).Unwrap ()
418427
with _ ->
419428
compensation ()
420429
reraise ()
@@ -447,15 +456,8 @@ module Task =
447456
let fallbackTask = nullArgCheck (nameof fallbackTask) fallbackTask
448457
let source = nullArgCheck (nameof source) source
449458
orElseWith (fun _ -> fallbackTask) source
450-
451-
/// Creates a Task from a value
452-
let result (value: 'T) = Task.FromResult value
453459

454-
/// Raises an exception in the Task
455-
let raise<'T> (e: exn) =
456-
let tcs = TaskCompletionSource<'T> ()
457-
tcs.SetException e
458-
tcs.Task
460+
459461

460462

461463
/// Workaround to fix signatures without breaking binary compatibility.

0 commit comments

Comments
 (0)