@@ -5,99 +5,113 @@ namespace FSharpPlus
55/// Additional operations on ValueTask<'T>
66[<RequireQualifiedAccess>]
77module ValueTask =
8-
9- open System.Threading
8+
109 open System.Threading .Tasks
10+
11+ let inline internal (| Succeeded | Canceled | Faulted |) ( t : ValueTask < 'T >) =
12+ if t.IsCompletedSuccessfully then Succeeded t.Result
13+ elif t.IsCanceled then Canceled
14+ else Faulted ( t.AsTask() .Exception.InnerExceptions)
1115
12- let FromResult < 'T > ( result : 'T ) =
13- ValueTask< 'T>( result)
14-
15- let FromException < 'T > ( e : exn ) =
16- ValueTask< 'T>( Task.FromException< 'T>( e))
17-
18- let FromCanceled < 'T > ( ct : CancellationToken ) =
19- ValueTask< 'T>( Task.FromCanceled< 'T>( ct))
20-
21- let FromTask < 'T > ( t : Task < 'T >) =
22- ValueTask< 'T>( t)
16+ let inline internal continueTask ( tcs : TaskCompletionSource < 'Result >) ( x : ValueTask < 't >) ( k : 't -> unit ) =
17+ let f = function
18+ | Succeeded r -> k r
19+ | Canceled -> tcs.SetCanceled ()
20+ | Faulted e -> tcs.SetException e
21+ if x.IsCompleted then f x
22+ else
23+ let aw = x.GetAwaiter ()
24+ aw.OnCompleted ( fun () -> f x)
2325
2426 /// <summary>Creates a ValueTask workflow from 'source' another, mapping its result with 'f'.</summary>
27+ /// <param name="f">The mapping function.</param>
28+ /// <param name="source">ValueTask workflow.</param>
2529 let map ( f : 'T -> 'U ) ( source : ValueTask < 'T >) : ValueTask < 'U > =
26- backgroundTask {
27- let! r = source
28- return f r
29- } |> ValueTask< 'U>
30+ let tcs = TaskCompletionSource< 'U> ()
31+ continueTask tcs source ( fun x ->
32+ try tcs.SetResult ( f x)
33+ with e -> tcs.SetException e)
34+ tcs.Task |> ValueTask< 'U>
35+
3036
3137 /// <summary>Creates a ValueTask workflow from two workflows 'x' and 'y', mapping its results with 'f'.</summary>
3238 /// <remarks>Workflows are run in sequence.</remarks>
3339 /// <param name="f">The mapping function.</param>
3440 /// <param name="x">First ValueTask workflow.</param>
3541 /// <param name="y">Second ValueTask workflow.</param>
3642 let map2 ( f : 'T -> 'U -> 'V ) ( x : ValueTask < 'T >) ( y : ValueTask < 'U >) : ValueTask < 'V > =
37- backgroundTask {
38- let! rX = x
39- let! rY = y
40- return f rX rY
41- } |> ValueTask< 'V>
43+ let tcs = TaskCompletionSource< 'V> ()
44+ continueTask tcs x ( fun x ->
45+ continueTask tcs y ( fun y ->
46+ try tcs.SetResult ( f x y)
47+ with e -> tcs.SetException e))
48+ tcs.Task |> ValueTask< 'V>
4249
4350 /// <summary>Creates a ValueTask workflow from three workflows 'x', 'y' and z, mapping its results with 'f'.</summary>
4451 /// <remarks>Workflows are run in sequence.</remarks>
4552 /// <param name="f">The mapping function.</param>
4653 /// <param name="x">First ValueTask workflow.</param>
4754 /// <param name="y">Second ValueTask workflow.</param>
4855 /// <param name="z">Third ValueTask workflow.</param>
49- let map3 ( f : 'T -> 'U -> 'V -> 'W ) ( x : ValueTask < 'T >) ( y : ValueTask < 'U >) ( z : ValueTask < 'V >) : ValueTask < 'W > =
50- backgroundTask {
51- let! rX = x
52- let! rY = y
53- let! rZ = z
54- return f rX rY rZ
55- } |> ValueTask< 'W>
56+ let map3 ( f : 'T -> 'U -> 'V -> 'W ) ( x : ValueTask < 'T >) ( y : ValueTask < 'U >) ( z : ValueTask < 'V >) : ValueTask < 'W > =
57+ let tcs = TaskCompletionSource< 'W> ()
58+ continueTask tcs x ( fun x ->
59+ continueTask tcs y ( fun y ->
60+ continueTask tcs z ( fun z ->
61+ try tcs.SetResult ( f x y z)
62+ with e -> tcs.SetException e)))
63+ tcs.Task |> ValueTask< 'W>
5664
5765 /// <summary>Creates a ValueTask workflow that is the result of applying the resulting function of a ValueTask workflow
5866 /// to the resulting value of another ValueTask workflow</summary>
5967 /// <param name="f">ValueTask workflow returning a function</param>
6068 /// <param name="x">ValueTask workflow returning a value</param>
6169 let apply ( f : ValueTask < 'T -> 'U >) ( x : ValueTask < 'T >) : ValueTask < 'U > =
62- backgroundTask {
63- let! r = x
64- let! fn = f
65- return ( fn r)
66- } |> ValueTask< 'U>
70+ let tcs = TaskCompletionSource< 'U> ()
71+ continueTask tcs f ( fun f ->
72+ continueTask tcs x ( fun x ->
73+ try tcs.SetResult ( f x)
74+ with e -> tcs.SetException e))
75+ tcs.Task |> ValueTask< 'U>
6776
6877 /// <summary>Creates a ValueTask workflow from two workflows 'x' and 'y', tupling its results.</summary>
6978 let zip ( x : ValueTask < 'T >) ( y : ValueTask < 'U >) : ValueTask < 'T * 'U > =
70- backgroundTask {
71- let! rX = x
72- let! rY = y
73- return ( rX , rY )
74- } |> ValueTask< 'T * 'U>
79+ let tcs = TaskCompletionSource < 'T * 'U > ()
80+ continueTask tcs x ( fun x ->
81+ continueTask tcs y ( fun y ->
82+ tcs.SetResult ( x , y )) )
83+ tcs.Task |> ValueTask< 'T * 'U>
7584
7685 /// Flattens two nested ValueTask into one.
7786 let join ( source : ValueTask < ValueTask < 'T >>) : ValueTask < 'T > =
78- backgroundTask {
79- let! s = source
80- return ! s
81- } |> ValueTask< 'T>
87+ let tcs = TaskCompletionSource< 'T> ()
88+ continueTask tcs source ( fun x ->
89+ continueTask tcs x ( fun x ->
90+ tcs.SetResult x))
91+ tcs.Task |> ValueTask< 'T>
8292
8393
8494 /// <summary>Creates a ValueTask workflow from 'source' workflow, mapping and flattening its result with 'f'.</summary>
8595 let bind ( f : 'T -> ValueTask < 'U >) ( source : ValueTask < 'T >) : ValueTask < 'U > =
86- source
87- |> map f
88- |> join
96+ let tcs = TaskCompletionSource< 'U> ()
97+ continueTask tcs source ( fun x ->
98+ try
99+ continueTask tcs ( f x) ( fun fx ->
100+ tcs.SetResult fx)
101+ with e -> tcs.SetException e)
102+ tcs.Task |> ValueTask< 'U>
89103
90104 /// <summary>Creates a ValueTask that ignores the result of the source ValueTask.</summary>
91105 /// <remarks>It can be used to convert non-generic ValueTask to unit ValueTask.</remarks>
92106 let ignore ( source : ValueTask < 'T >) =
93- backgroundTask {
94- let! _ = source
95- return ()
96- } |> ValueTask
107+ if source.IsCompletedSuccessfully then
108+ source.GetAwaiter() .GetResult() |> ignore
109+ Unchecked.defaultof<_>
110+ else
111+ new ValueTask ( source.AsTask ())
97112
98113
99114 /// Raises an exception in the ValueTask
100- let raise ( e : exn ) =
101- FromException e
115+ let raise ( ``exception`` : exn ) = ValueTask< 'TResult> ( Task.FromException< 'TResult> `` exception `` )
102116
103117#endif
0 commit comments