Skip to content

Commit eb91d17

Browse files
committed
Use task CE
1 parent c645fbd commit eb91d17

File tree

2 files changed

+47
-123
lines changed

2 files changed

+47
-123
lines changed

src/FSharpPlus/Extensions/Task.fs

Lines changed: 22 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -68,20 +68,11 @@ module Task =
6868
/// <returns>The resulting task workflow.</returns>
6969
let map (mapper: 'T -> 'U) (source: Task<'T>) : Task<'U> =
7070
let source = nullArgCheck (nameof source) source
71-
72-
if source.IsCompleted then
73-
match source with
74-
| Succeeded r -> try result (mapper r) with e -> raise e
75-
| Faulted aex -> raise aex
76-
| Canceled -> canceled
77-
else
78-
let tcs = TaskCompletionSource<'U> ()
79-
let k = function
80-
| Succeeded r -> try tcs.SetResult (mapper r) with e -> tcs.SetException e
81-
| Faulted exn -> tcs.SetException exn.InnerExceptions
82-
| Canceled -> tcs.SetCanceled ()
83-
continueWith k source
84-
tcs.Task
71+
72+
task {
73+
let! r = source
74+
return mapper r
75+
}
8576

8677
/// <summary>Creates a task workflow from two workflows 'task1' and 'task2', mapping its results with 'mapper'.</summary>
8778
/// <remarks>Workflows are run in sequence.</remarks>
@@ -386,16 +377,19 @@ module Task =
386377
let join (source: Task<Task<'T>>) : Task<'T> =
387378
let source = nullArgCheck (nameof source) source
388379

389-
if source.IsCompleted then
390-
match source with
391-
| Succeeded inner -> inner
392-
| Faulted aex -> raise aex
393-
| Canceled -> canceled
394-
else
395-
source.Unwrap()
380+
task {
381+
let! inner = source
382+
return! inner
383+
}
396384

397385
/// <summary>Creates a task workflow from 'source' workflow, mapping and flattening its result with 'f'.</summary>
398-
let bind (f: 'T -> Task<'U>) (source: Task<'T>) : Task<'U> = source |> Unchecked.nonNull |> map f |> join
386+
let bind (f: 'T -> Task<'U>) (source: Task<'T>) : Task<'U> =
387+
let source = nullArgCheck (nameof source) source
388+
389+
task {
390+
let! r = source
391+
return! f r
392+
}
399393

400394
/// <summary>Creates a task that ignores the result of the source task.</summary>
401395
/// <remarks>It can be used to convert non-generic Task to unit Task.</remarks>
@@ -418,37 +412,14 @@ module Task =
418412
tcs.Task
419413

420414
[<ObsoleteAttribute("Swap parameters")>]
421-
let tryWith (body: unit -> Task<'T>) (compensation: exn -> Task<'T>) : Task<'T> =
422-
let unwrapException (agg: AggregateException) =
423-
if agg.InnerExceptions.Count = 1 then agg.InnerExceptions.[0]
424-
else agg :> Exception
425-
let task =
426-
try body ()
427-
with
428-
| :? AggregateException as exn -> compensation (unwrapException exn)
429-
| exn -> compensation exn
430-
431-
let k = function
432-
| Succeeded _ -> task
433-
| Faulted exn -> task.ContinueWith(fun (_: Task<'T>) -> compensation (unwrapException exn)).Unwrap ()
434-
| Canceled -> task.ContinueWith(fun (_: Task<'T>) -> compensation (TaskCanceledException())).Unwrap ()
435-
if task.IsCompleted then k task
436-
else (task.ContinueWith k).Unwrap ()
415+
let tryWith (body: unit -> Task<'T>) (compensation: exn -> Task<'T>) : Task<'T> = task {
416+
try return! body ()
417+
with e -> return! compensation e }
437418

438419
[<ObsoleteAttribute("Swap parameters")>]
439-
let tryFinally (body: unit -> Task<'T>) (compensation : unit -> unit) : Task<'T> =
440-
let mutable ran = false
441-
let compensation () =
442-
if not ran then
443-
ran <- true
444-
compensation ()
445-
try
446-
let task = body ()
447-
if task.IsCompleted then compensation (); task
448-
else task.ContinueWith(fun (_: Task<'T>) -> compensation (); task).Unwrap ()
449-
with _ ->
450-
compensation ()
451-
reraise ()
420+
let tryFinally (body: unit -> Task<'T>) (compensation : unit -> unit) : Task<'T> = task {
421+
try return! body ()
422+
finally compensation () }
452423

453424
/// Used to de-sugar use .. blocks in Computation Expressions.
454425
let using (disp: 'T when 'T :> IDisposable) (body: 'T -> Task<'U>) =

src/FSharpPlus/Extensions/ValueTask.fs

Lines changed: 25 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ module ValueTask =
2121
let inline continueTask (tcs: TaskCompletionSource<'Result>) (x: ValueTask<'t>) (k: 't -> unit) =
2222
let f = function
2323
| Succeeded r -> k r
24-
| Canceled -> tcs.SetCanceled ()
25-
| Faulted e -> tcs.SetException e.InnerExceptions
24+
| Faulted axn -> tcs.SetException axn.InnerExceptions
25+
| Canceled -> tcs.SetCanceled ()
2626
if x.IsCompleted then f x
2727
else x.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted (fun () -> f x)
2828

@@ -70,19 +70,10 @@ module ValueTask =
7070
/// <param name="source">The source ValueTask workflow.</param>
7171
/// <returns>The resulting ValueTask workflow.</returns>
7272
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
73+
task {
74+
let! r = source
75+
return mapper r
76+
} |> ValueTask<'U>
8677

8778

8879
/// <summary>Creates a ValueTask workflow from two workflows 'x' and 'y', mapping its results with 'f'.</summary>
@@ -143,8 +134,8 @@ module ValueTask =
143134
let k (v: ref<_>) i t =
144135
match t with
145136
| Succeeded r -> v.Value <- r
137+
| Faulted aex -> failures[i] <- aex.InnerExceptions
146138
| Canceled -> cancelled <- true
147-
| Faulted e -> failures[i] <- e.InnerExceptions
148139
trySet ()
149140

150141
if task1.IsCompleted && task2.IsCompleted then
@@ -191,8 +182,8 @@ module ValueTask =
191182
let k (v: ref<_>) i t =
192183
match t with
193184
| Succeeded r -> v.Value <- r
185+
| Faulted aex -> failures[i] <- aex.InnerExceptions
194186
| Canceled -> cancelled <- true
195-
| Faulted e -> failures[i] <- e.InnerExceptions
196187
trySet ()
197188

198189
if task1.IsCompleted && task2.IsCompleted && task3.IsCompleted then
@@ -236,20 +227,18 @@ module ValueTask =
236227

237228
/// Flattens two nested ValueTask into one.
238229
let join (source: ValueTask<ValueTask<'T>>) : ValueTask<'T> =
239-
if source.IsCompleted then
240-
match source with
241-
| Succeeded inner -> inner
242-
| Faulted aex -> raise aex
243-
| Canceled -> canceled
244-
else
245-
let tcs = TaskCompletionSource<'T> ()
246-
continueTask tcs source (fun inner ->
247-
continueTask tcs inner tcs.SetResult)
248-
ValueTask<'T> tcs.Task
230+
task {
231+
let! inner = source
232+
return! inner
233+
} |> ValueTask<'T>
249234

250235

251236
/// <summary>Creates a ValueTask workflow from 'source' workflow, mapping and flattening its result with 'f'.</summary>
252-
let bind (f: 'T -> ValueTask<'U>) (source: ValueTask<'T>) : ValueTask<'U> = source |> Unchecked.nonNull |> map f |> join
237+
let bind (f: 'T -> ValueTask<'U>) (source: ValueTask<'T>) : ValueTask<'U> =
238+
task {
239+
let! r = source
240+
return! f r
241+
} |> ValueTask<'U>
253242

254243
/// <summary>Creates a ValueTask that ignores the result of the source ValueTask.</summary>
255244
/// <remarks>It can be used to convert non-generic ValueTask to unit ValueTask.</remarks>
@@ -272,53 +261,17 @@ module ValueTask =
272261

273262
/// Used to de-sugar try .. with .. blocks in Computation Expressions.
274263
let inline tryWith ([<InlineIfLambda>]compensation: exn -> ValueTask<'T>) ([<InlineIfLambda>]body: unit -> ValueTask<'T>) : ValueTask<'T> =
275-
let unwrapException (agg: AggregateException) =
276-
if agg.InnerExceptions.Count = 1 then agg.InnerExceptions.[0]
277-
else agg :> Exception
278-
279-
let mutable ran = false
280-
281-
let compensation exn =
282-
if not ran then ran <- true
283-
try compensation exn
284-
with e -> raise e
285-
286-
let task =
287-
try body ()
288-
with
289-
| :? AggregateException as aex -> compensation (unwrapException aex)
290-
| exn -> compensation exn
291-
if ran then task
292-
elif task.IsCompleted then
293-
match task with
294-
| Succeeded _ -> task
295-
| Faulted aex -> compensation (unwrapException aex)
296-
| Canceled -> compensation (TaskCanceledException ())
297-
else
298-
let tcs = TaskCompletionSource<'T> ()
299-
let f = function
300-
| Succeeded r -> tcs.SetResult r
301-
| Faulted aex -> continueTask tcs (compensation (unwrapException aex)) (fun r -> try tcs.SetResult r with e -> tcs.SetException e)
302-
| Canceled -> continueTask tcs (compensation (TaskCanceledException ())) (fun r -> try tcs.SetResult r with e -> tcs.SetException e)
303-
task.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted (fun () -> f task)
304-
ValueTask<'T> tcs.Task
264+
task {
265+
try return! body ()
266+
with e -> return! compensation e
267+
} |> ValueTask<'T>
305268

306269
/// Used to de-sugar try .. finally .. blocks in Computation Expressions.
307270
let inline tryFinally ([<InlineIfLambda>]compensation : unit -> unit) ([<InlineIfLambda>]body: unit -> ValueTask<'T>) : ValueTask<'T> =
308-
let mutable ran = false
309-
let compensation () =
310-
if not ran then
311-
ran <- true
312-
compensation ()
313-
try
314-
let task = body ()
315-
if task.IsCompleted then compensation (); task
316-
else
317-
let t = task.AsTask()
318-
t.ContinueWith(fun (_: Task<'T>) -> compensation (); t).Unwrap () |> ValueTask<'T>
319-
with _ ->
320-
compensation ()
321-
reraise ()
271+
task {
272+
try return! body ()
273+
finally compensation ()
274+
} |> ValueTask<'T>
322275

323276
/// Used to de-sugar use .. blocks in Computation Expressions.
324277
let inline using (disp: 'T when 'T :> IDisposable) ([<InlineIfLambda>]body: 'T -> ValueTask<'U>) =

0 commit comments

Comments
 (0)