@@ -63,10 +63,15 @@ module ValueTask =
6363 /// <param name =" source " >The source ValueTask workflow.</param >
6464 /// <returns >The resulting ValueTask workflow.</returns >
6565 let map ( mapper : 'T -> 'U ) ( source : ValueTask < 'T >) : ValueTask < 'U > =
66- backgroundTask {
67- let! r = source
68- return mapper r
69- } |> ValueTask< 'U>
66+ if source.IsCompleted then
67+ match source with
68+ | Succeeded r -> try result ( mapper r) with e -> ValueTask.FromException<_> e
69+ | Faulted exn -> FromExceptions exn
70+ | Canceled -> canceled
71+ else
72+ let tcs = TaskCompletionSource< 'U> TaskCreationOptions.RunContinuationsAsynchronously
73+ source |> continueTask tcs ( fun r -> try tcs.SetResult ( mapper r) with e -> tcs.SetException e)
74+ tcs.Task |> ValueTask< 'U>
7075
7176
7277 /// <summary >Creates a ValueTask workflow from two workflows 'x' and 'y', mapping its results with 'f'.</summary >
@@ -271,17 +276,11 @@ module ValueTask =
271276
272277 /// Flattens two nested ValueTask into one.
273278 let join ( source : ValueTask < ValueTask < 'T >>) : ValueTask < 'T > =
274- backgroundTask {
275- let! inner = source
276- return ! inner
277- } |> ValueTask< 'T>
279+ ( source |> map ( fun x -> x.AsTask())) .AsTask() .Unwrap () |> ValueTask< 'T>
278280
279281 /// <summary >Creates a ValueTask workflow from 'source' workflow, mapping and flattening its result with 'f'.</summary >
280282 let bind ( f : 'T -> ValueTask < 'U >) ( source : ValueTask < 'T >) : ValueTask < 'U > =
281- backgroundTask {
282- let! r = source
283- return ! f r
284- } |> ValueTask< 'U>
283+ source |> map f |> join
285284
286285 /// <summary >Creates a ValueTask that ignores the result of the source ValueTask.</summary >
287286 /// <param name =" source " >The source ValueTask.</param >
@@ -302,17 +301,38 @@ module ValueTask =
302301
303302 /// Used to de-sugar try .. with .. blocks in Computation Expressions.
304303 let inline tryWith ( [<InlineIfLambda>] compensation : exn -> ValueTask < 'T >) ( [<InlineIfLambda>] body : unit -> ValueTask < 'T >) : ValueTask < 'T > =
305- backgroundTask {
306- try return ! body ()
307- with e -> return ! compensation e
308- } |> ValueTask< 'T>
304+ let unwrapException ( agg : AggregateException ) =
305+ if agg.InnerExceptions.Count = 1 then agg.InnerExceptions.[ 0 ]
306+ else agg :> Exception
307+ try Ok ( body ()) with e -> Error e
308+ |> function
309+ | Ok task ->
310+ if task.IsCompleted then
311+ match task with
312+ | Succeeded _ -> task
313+ | Faulted aex -> compensation ( unwrapException aex)
314+ | Canceled -> canceled
315+ else
316+ task.AsTask() .ContinueWith(( fun ( x : Task < 'T >) -> Task.tryWith ( compensation >> fun x -> x.AsTask()) ( fun () -> x))) .Unwrap () |> ValueTask< 'T>
317+ | Error (:? AggregateException as exn) -> compensation ( unwrapException exn)
318+ | Error exn -> compensation exn
319+
309320
310321 /// Used to de-sugar try .. finally .. blocks in Computation Expressions.
311322 let inline tryFinally ( [<InlineIfLambda>] compensation : unit -> unit ) ( [<InlineIfLambda>] body : unit -> ValueTask < 'T >) : ValueTask < 'T > =
312- backgroundTask {
313- try return ! body ()
314- finally compensation ()
315- } |> ValueTask< 'T>
323+ let mutable ran = false
324+ let compensation () =
325+ if not ran then
326+ ran <- true
327+ compensation ()
328+ try
329+ let task = body() .AsTask ()
330+ if task.IsCompleted then compensation (); task
331+ else task.ContinueWith( fun ( _ : Task < 'T >) -> compensation (); task) .Unwrap ()
332+ with _ ->
333+ compensation ()
334+ reraise ()
335+ |> ValueTask< 'T>
316336
317337 /// Used to de-sugar use .. blocks in Computation Expressions.
318338 let inline using ( disp : 'T when 'T :> IDisposable ) ( [<InlineIfLambda>] body : 'T -> ValueTask < 'U >) =
0 commit comments