@@ -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,41 @@ 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 runCompensation exn =
305+ try compensation exn
306+ with e -> ValueTask.FromException< 'T> e
307+ let unwrapException ( agg : AggregateException ) =
308+ if agg.InnerExceptions.Count = 1 then agg.InnerExceptions.[ 0 ]
309+ else agg :> Exception
310+ try Ok ( body ()) with e -> Error e
311+ |> function
312+ | Ok task ->
313+ if task.IsCompleted then
314+ match task with
315+ | Succeeded _ -> task
316+ | Faulted aex -> runCompensation ( unwrapException aex)
317+ | Canceled -> canceled
318+ else
319+ task.AsTask() .ContinueWith( fun ( x : Task < 'T >) -> Task.tryWith ( compensation >> fun x -> x.AsTask()) ( fun () -> x)) .Unwrap () |> ValueTask< 'T>
320+ | Error exn -> runCompensation exn
321+
309322
310323 /// Used to de-sugar try .. finally .. blocks in Computation Expressions.
311324 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>
325+ let task =
326+ try body ()
327+ with _ ->
328+ try
329+ compensation ()
330+ reraise ()
331+ with e -> ValueTask.FromException< 'T> e
332+ if task.IsCompleted then
333+ try
334+ compensation ()
335+ task
336+ with e -> ValueTask.FromException< 'T> e
337+ else
338+ task.AsTask() .ContinueWith( fun ( x : Task < 'T >) -> Task.tryFinally compensation ( fun () -> x)) .Unwrap () |> ValueTask< 'T>
316339
317340 /// Used to de-sugar use .. blocks in Computation Expressions.
318341 let inline using ( disp : 'T when 'T :> IDisposable ) ( [<InlineIfLambda>] body : 'T -> ValueTask < 'U >) =
0 commit comments