@@ -26,29 +26,63 @@ 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
3740 #else
3841 let tcs = TaskCompletionSource< 'T> ()
3942 tcs.SetResult value
40- tcs.Task |> ValueTask< 'T>
43+ ValueTask< 'T> tcs.Task
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>
@@ -121,9 +155,9 @@ module ValueTask =
121155 task1 |> k r1 0
122156 task2 |> k r2 1
123157 else
124- continueWith task1 ( k r1 0 )
125- continueWith task2 ( k r2 1 )
126- tcs.Task |> ValueTask< 'U>
158+ continueWith ( k r1 0 ) task1
159+ continueWith ( k r2 1 ) task2
160+ ValueTask< 'U> tcs.Task
127161
128162 /// <summary>Creates a ValueTask workflow from three workflows, mapping its results with a specified function.</summary>
129163 /// <remarks>Similar to lift3 but although workflows are started in sequence they might end independently in different order
@@ -170,10 +204,10 @@ module ValueTask =
170204 task2 |> k r2 1
171205 task3 |> k r3 2
172206 else
173- continueWith task1 ( k r1 0 )
174- continueWith task2 ( k r2 1 )
175- continueWith task3 ( k r3 2 )
176- tcs.Task |> ValueTask< 'U>
207+ continueWith ( k r1 0 ) task1
208+ continueWith ( k r2 1 ) task2
209+ continueWith ( k r3 2 ) task3
210+ ValueTask< 'U> tcs.Task
177211
178212 /// <summary>Creates a ValueTask workflow that is the result of applying the resulting function of a ValueTask workflow
179213 /// to the resulting value of another ValueTask workflow</summary>
@@ -313,7 +347,4 @@ module ValueTask =
313347 /// <returns>The option if the option is Some, else the alternate option.</returns>
314348 let orElse ( fallbackValueTask : ValueTask < 'T >) ( source : ValueTask < 'T >) : ValueTask < 'T > = orElseWith ( fun _ -> fallbackValueTask) source
315349
316- /// Raises an exception in the ValueTask
317- let raise < 'TResult > ( ``exception`` : exn ) = ValueTask< 'TResult> ( Task.FromException< 'TResult> `` exception `` )
318-
319350#endif
0 commit comments