@@ -26,11 +26,14 @@ module ValueTask =
2626 if x.IsCompleted then f x
2727 else x.ConfigureAwait( false ) .GetAwaiter() .UnsafeOnCompleted ( fun () -> f x)
2828
29- let inline continueWith ( x : ValueTask < 't >) f =
29+ let inline continueWith f ( x : ValueTask < 't >) =
3030 if x.IsCompleted then f x
3131 else x.ConfigureAwait( false ) .GetAwaiter() .UnsafeOnCompleted ( fun () -> f x)
3232
33- /// Creates a ValueTask from a value
33+
34+ /// <summary >Creates a ValueTask that's completed successfully with the specified value.</summary >
35+ /// <param name =" value " ></param >
36+ /// <returns >A ValueTask that is completed successfully with the specified value.</returns >
3437 let result ( value : 'T ) : ValueTask < 'T > =
3538 #if NET5_ 0_ OR_ GREATER
3639 ValueTask.FromResult value
@@ -39,45 +42,72 @@ module ValueTask =
3942 tcs.SetResult value
4043 tcs.Task |> ValueTask< 'T>
4144 #endif
45+
46+ /// <summary >Creates a ValueTask that's completed unsuccessfully with the specified exception.</summary >
47+ /// <param name =" exn " >The exception to be raised.</param >
48+ /// <returns >A ValueTask that is completed unsuccessfully with the specified exception.</returns >
49+ /// <remarks >
50+ /// If the exception is not an AggregateException it is wrapped into one.
51+ /// Prefer this function over ValueTask.FromException as it handles AggregateExceptions correctly.
52+ /// </remarks >
53+ let raise < 'T > ( exn : exn ) : ValueTask < 'T > =
54+ match exn with
55+ | :? AggregateException as agg when agg.InnerExceptions.Count > 1 ->
56+ let tcs = TaskCompletionSource< 'T> ()
57+ tcs.SetException agg.InnerExceptions
58+ ValueTask< 'T> tcs.Task
59+ | :? AggregateException as agg -> ValueTask.FromException< 'T> agg.InnerExceptions[ 0 ]
60+ | exn -> ValueTask.FromException< 'T> exn
4261
43- /// <summary >Creates a ValueTask workflow from 'source' another, mapping its result with 'f'.</summary >
44- /// <param name =" f " >The mapping function.</param >
45- /// <param name =" source " >ValueTask workflow.</param >
46- let map ( f : 'T -> 'U ) ( source : ValueTask < 'T >) : ValueTask < 'U > =
47- let tcs = TaskCompletionSource< 'U> ()
48- continueTask tcs source ( fun x ->
49- try tcs.SetResult ( f x)
50- with e -> tcs.SetException e)
51- tcs.Task |> ValueTask< 'U>
62+ let private cancellationTokenSingleton = CancellationToken true
63+
64+ /// <summary >Creates a ValueTask that's canceled.</summary >
65+ /// <returns >A ValueTask that's canceled.</returns >
66+ let canceled < 'T > : ValueTask < 'T > = ValueTask.FromCanceled< 'T> cancellationTokenSingleton
67+
68+ /// <summary >Creates a ValueTask workflow from 'source' workflow, mapping its result with 'mapper'.</summary >
69+ /// <param name =" mapper " >The mapping function.</param >
70+ /// <param name =" source " >The source ValueTask workflow.</param >
71+ /// <returns >The resulting ValueTask workflow.</returns >
72+ let map ( mapper : 'T -> 'U ) ( source : ValueTask < 'T >) : ValueTask < 'U > =
73+ if source.IsCompleted then
74+ match source with
75+ | Succeeded r -> try result ( mapper r) with e -> raise e
76+ | Faulted exn -> raise exn
77+ | Canceled -> canceled
78+ else
79+ let tcs = TaskCompletionSource< 'U> ()
80+ let k = function
81+ | Succeeded r -> try tcs.SetResult ( mapper r) with e -> tcs.SetException e
82+ | Faulted exn -> tcs.SetException exn.InnerExceptions
83+ | Canceled -> tcs.SetCanceled ()
84+ continueWith k source
85+ ValueTask< 'U> tcs.Task
5286
5387
5488 /// <summary >Creates a ValueTask workflow from two workflows 'x' and 'y', mapping its results with 'f'.</summary >
5589 /// <remarks >Workflows are run in sequence.</remarks >
5690 /// <param name =" f " >The mapping function.</param >
5791 /// <param name =" x " >First ValueTask workflow.</param >
5892 /// <param name =" y " >Second ValueTask workflow.</param >
59- let lift2 ( f : 'T -> 'U -> 'V ) ( x : ValueTask < 'T >) ( y : ValueTask < 'U >) : ValueTask < 'V > =
60- let tcs = TaskCompletionSource< 'V> ()
61- continueTask tcs x ( fun x ->
62- continueTask tcs y ( fun y ->
63- try tcs.SetResult ( f x y)
64- with e -> tcs.SetException e))
65- tcs.Task |> ValueTask< 'V>
66-
93+ let lift2 ( f : 'T1 -> 'T2 -> 'U ) ( task1 : ValueTask < 'T1 >) ( task2 : ValueTask < 'T2 >) : ValueTask < 'U > =
94+ let tcs = TaskCompletionSource< 'U> ()
95+ continueTask tcs task1 ( fun x ->
96+ continueTask tcs task2 ( fun y -> try tcs.SetResult ( f x y) with e -> tcs.SetException e))
97+ ValueTask< 'U> tcs.Task
98+
6799 /// <summary >Creates a ValueTask workflow from three workflows 'x', 'y' and z, mapping its results with 'f'.</summary >
68100 /// <remarks >Workflows are run in sequence.</remarks >
69101 /// <param name =" f " >The mapping function.</param >
70102 /// <param name =" x " >First ValueTask workflow.</param >
71103 /// <param name =" y " >Second ValueTask workflow.</param >
72104 /// <param name =" z " >Third ValueTask workflow.</param >
73- let lift3 ( f : 'T -> 'U -> 'V -> 'W ) ( x : ValueTask < 'T >) ( y : ValueTask < 'U >) ( z : ValueTask < 'V >) : ValueTask < 'W > =
74- let tcs = TaskCompletionSource< 'W > ()
105+ let lift3 ( f : 'T1 -> 'T2 -> 'T3 -> 'U ) ( x : ValueTask < 'T1 >) ( y : ValueTask < 'T2 >) ( z : ValueTask < 'T3 >) : ValueTask < 'U > =
106+ let tcs = TaskCompletionSource< 'U > ()
75107 continueTask tcs x ( fun x ->
76108 continueTask tcs y ( fun y ->
77- continueTask tcs z ( fun z ->
78- try tcs.SetResult ( f x y z)
79- with e -> tcs.SetException e)))
80- tcs.Task |> ValueTask< 'W>
109+ continueTask tcs z ( fun z -> try tcs.SetResult ( f x y z) with e -> tcs.SetException e)))
110+ ValueTask< 'U> tcs.Task
81111
82112 /// <summary >Creates a ValueTask workflow from two workflows, mapping its results with a specified function.</summary >
83113 /// <remarks >Similar to lift2 but although workflows are started in sequence they might end independently in different order
@@ -121,9 +151,9 @@ module ValueTask =
121151 task1 |> k r1 0
122152 task2 |> k r2 1
123153 else
124- continueWith task1 ( k r1 0 )
125- continueWith task2 ( k r2 1 )
126- tcs.Task |> ValueTask< 'U>
154+ continueWith ( k r1 0 ) task1
155+ continueWith ( k r2 1 ) task2
156+ ValueTask< 'U> tcs.Task
127157
128158 /// <summary >Creates a ValueTask workflow from three workflows, mapping its results with a specified function.</summary >
129159 /// <remarks >Similar to lift3 but although workflows are started in sequence they might end independently in different order
@@ -139,7 +169,7 @@ module ValueTask =
139169 with e ->
140170 let tcs = TaskCompletionSource<_> ()
141171 tcs.SetException e
142- tcs.Task |> ValueTask< 'U>
172+ ValueTask< 'U> tcs.Task
143173 else
144174 let tcs = TaskCompletionSource<_> ()
145175 let r1 = ref Unchecked.defaultof<_>
@@ -170,10 +200,10 @@ module ValueTask =
170200 task2 |> k r2 1
171201 task3 |> k r3 2
172202 else
173- continueWith task1 ( k r1 0 )
174- continueWith task2 ( k r2 1 )
175- continueWith task3 ( k r3 2 )
176- tcs.Task |> ValueTask< 'U>
203+ continueWith ( k r1 0 ) task1
204+ continueWith ( k r2 1 ) task2
205+ continueWith ( k r3 2 ) task3
206+ ValueTask< 'U> tcs.Task
177207
178208 /// <summary >Creates a ValueTask workflow that is the result of applying the resulting function of a ValueTask workflow
179209 /// to the resulting value of another ValueTask workflow</summary >
@@ -182,18 +212,15 @@ module ValueTask =
182212 let apply ( f : ValueTask < 'T -> 'U >) ( x : ValueTask < 'T >) : ValueTask < 'U > =
183213 let tcs = TaskCompletionSource< 'U> ()
184214 continueTask tcs f ( fun f ->
185- continueTask tcs x ( fun x ->
186- try tcs.SetResult ( f x)
187- with e -> tcs.SetException e))
188- tcs.Task |> ValueTask< 'U>
215+ continueTask tcs x ( fun x -> try tcs.SetResult ( f x) with e -> tcs.SetException e))
216+ ValueTask< 'U> tcs.Task
189217
190218 /// <summary >Creates a ValueTask workflow from two workflows 'x' and 'y', tupling its results.</summary >
191- let zipSequentially ( x : ValueTask < 'T >) ( y : ValueTask < 'U >) : ValueTask < 'T * 'U > =
192- let tcs = TaskCompletionSource< 'T * 'U> ()
193- continueTask tcs x ( fun x ->
194- continueTask tcs y ( fun y ->
195- tcs.SetResult ( x, y)))
196- tcs.Task |> ValueTask< 'T * 'U>
219+ let zipSequentially ( task1 : ValueTask < 'T1 >) ( task2 : ValueTask < 'T2 >) : ValueTask < 'T1 * 'T2 > =
220+ let tcs = TaskCompletionSource< 'T1 * 'T2> ()
221+ continueTask tcs task1 ( fun x ->
222+ continueTask tcs task2 ( fun y -> tcs.SetResult ( x, y)))
223+ ValueTask< 'T1 * 'T2> tcs.Task
197224
198225 /// <summary >Creates a ValueTask workflow from two workflows, tupling its results.</summary >
199226 /// <remarks >Similar to zipSequentially but although workflows are started in sequence they might end independently in different order
@@ -306,7 +333,4 @@ module ValueTask =
306333 /// <returns >The option if the option is Some, else the alternate option.</returns >
307334 let orElse ( fallbackValueTask : ValueTask < 'T >) ( source : ValueTask < 'T >) : ValueTask < 'T > = orElseWith ( fun _ -> fallbackValueTask) source
308335
309- /// Raises an exception in the ValueTask
310- let raise < 'TResult > ( ``exception`` : exn ) = ValueTask< 'TResult> ( Task.FromException< 'TResult> `` exception `` )
311-
312336#endif
0 commit comments