Skip to content

Commit 2b2d902

Browse files
committed
Refactor TaskBuilderBaseRuntime to improve awaiter handling and update tests for consistency
1 parent 32c5589 commit 2b2d902

File tree

2 files changed

+32
-56
lines changed

2 files changed

+32
-56
lines changed

src/IcedTasks/TaskBuilderBase_Net10.fs

Lines changed: 29 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,23 @@ module internal AsyncHelpers =
2121
type TaskBuilderBaseRuntime() =
2222

2323

24-
member inline _.Return(value: 'T) = ValueTask.FromResult value
24+
member inline _.Return(value: 'T) =
25+
ValueTask.FromResult value
26+
|> Awaitable.GetAwaiter
2527

2628
// [<NoEagerConstraintApplication>]
2729
member inline _.Bind(awaiter, [<InlineIfLambda>] continuation) =
2830
AsyncHelpers.awaitAwaiter awaiter
2931
|> continuation
32+
// |> Awaitable.GetAwaiter
3033

3134

3235
// [<NoEagerConstraintApplication>]
3336
member inline this.ReturnFrom(awaiter) = this.Bind(awaiter, this.Return)
3437

35-
member inline _.Zero() = ValueTask<_>()
38+
member inline _.Zero() =
39+
ValueTask<_>()
40+
|> Awaitable.GetAwaiter
3641

3742
member inline _.Delay([<InlineIfLambda>] f: unit -> 'a) = f
3843

@@ -42,24 +47,24 @@ type TaskBuilderBaseRuntime() =
4247
// [<NoEagerConstraintApplication>]
4348
member inline this.MergeSources(awaiter1, awaiter2) =
4449
this.Bind(awaiter1, fun v1 -> this.Bind(awaiter2, fun v2 -> this.Return(struct (v1, v2))))
45-
|> Awaitable.GetAwaiter
50+
// |> Awaitable.GetAwaiter
4651

4752
member inline this.Combine(awaiter1, [<InlineIfLambda>] continuation) =
48-
this.Bind(Awaitable.GetAwaiter awaiter1, fun _ -> continuation ())
53+
this.Bind(awaiter1, fun _ -> continuation ())
4954

5055
member inline this.While
5156
([<InlineIfLambda>] guard: unit -> bool, [<InlineIfLambda>] body: unit -> 'a)
5257
=
5358
while guard () do
5459
body ()
55-
|> AsyncHelpers.awaitAwaitable
60+
|> AsyncHelpers.awaitAwaiter
5661

5762
this.Zero()
5863

5964
member inline this.For(sequence: seq<'T>, [<InlineIfLambda>] body: 'T -> 'a) =
6065
for x in sequence do
6166
body x
62-
|> AsyncHelpers.awaitAwaitable
67+
|> AsyncHelpers.awaitAwaiter
6368

6469
this.Zero()
6570

@@ -68,7 +73,7 @@ type TaskBuilderBaseRuntime() =
6873
([<InlineIfLambda>] awaiter, [<InlineIfLambda>] compensation: unit -> ValueTask)
6974
=
7075
try
71-
this.Bind(Awaitable.GetAwaiter(awaiter ()), this.Return)
76+
this.Bind((awaiter ()), this.Return)
7277
finally
7378
compensation ()
7479
|> AsyncHelpers.awaitAwaitable
@@ -77,15 +82,15 @@ type TaskBuilderBaseRuntime() =
7782
([<InlineIfLambda>] awaiter, [<InlineIfLambda>] compensation: unit -> unit)
7883
=
7984
try
80-
this.Bind(Awaitable.GetAwaiter(awaiter ()), this.Return)
85+
this.Bind((awaiter ()), this.Return)
8186
finally
8287
compensation ()
8388

84-
member inline this.TryWith
85-
([<InlineIfLambda>] awaiter, [<InlineIfLambda>] catchHandler: exn -> ValueTask<'a>)
86-
=
89+
member inline this.TryWith<'Awaiter>
90+
([<InlineIfLambda>] awaiter, [<InlineIfLambda>] catchHandler: exn -> 'Awaiter)
91+
: 'Awaiter =
8792
try
88-
this.Bind(Awaitable.GetAwaiter(awaiter ()), this.Return)
93+
awaiter ()
8994
with ex ->
9095
catchHandler ex
9196

@@ -110,7 +115,7 @@ type TaskBuilderBaseRuntime() =
110115
while enumerator.MoveNextAsync()
111116
|> AsyncHelpers.awaitAwaitable do
112117
body enumerator.Current
113-
|> AsyncHelpers.awaitAwaitable
118+
|> AsyncHelpers.awaitAwaiter
114119

115120
this.Zero()
116121
)
@@ -190,14 +195,13 @@ module HighPriority =
190195
type TaskBuilderRuntime() =
191196
inherit TaskBuilderBaseRuntime()
192197

193-
member inline this.Run([<InlineIfLambda>] f: unit -> ValueTask<'T>) : Task<'T> = f().AsTask()
198+
member inline this.Run([<InlineIfLambda>] f: unit -> 'a) : Task<'T> =
199+
AsyncHelpers.awaitAwaiter (f ())
200+
|> Task.FromResult
201+
// f().AsTask()
194202

195203

196-
/// <summary>Allows the computation expression to turn other types into 'Awaiter</summary>
197-
///
198-
/// <remarks>This turns a Task&lt;'T&gt; into a 'Awaiter.</remarks>
199-
///
200-
/// <returns>'Awaiter</returns>
204+
/// Used to force type inference to prefer Task<_> for parameters of functions using the build
201205
member inline _.Source(task: Task<'T>) = Awaitable.GetTaskAwaiter task
202206

203207

@@ -207,40 +211,13 @@ type ValueTaskBuilderRuntime() =
207211
member inline this.Run([<InlineIfLambda>] f: unit -> ValueTask<'T>) : ValueTask<'T> = f ()
208212

209213

210-
/// <summary>Allows the computation expression to turn other types into 'Awaiter</summary>
211-
///
212-
/// <remarks>This turns a Task&lt;'T&gt; into a 'Awaiter.</remarks>
213-
///
214-
/// <returns>'Awaiter</returns>
214+
/// Used to force type inference to prefer ValueTask<_> for parameters of functions using the build
215215
member inline _.Source(task: ValueTask<'T>) = Awaitable.GetAwaiter task
216216

217217

218-
module Testing =
219-
let taskRuntime = TaskBuilderRuntime()
220-
221-
let foo () =
222-
taskRuntime {
223-
let! x = Task.FromResult 42
224-
and! y = ValueTask.FromResult 42
225-
and! a = ValueTask.FromResult 42
226-
and! b = Task.FromResult 42
227-
and! c = ValueTask.FromResult 42
228-
and! z = Task.Run(fun () -> 42)
218+
namespace IcedTasks.Polyfill.TasksRuntime
229219

230-
do! Task.Yield()
231-
232-
if true then
233-
do! ValueTask.CompletedTask
234-
235-
let mutable i = 0
236-
237-
while i < 10 do
238-
do! ValueTask.CompletedTask
239-
i <- i + 1
240-
241-
for j in 1..5 do
242-
do! ValueTask.CompletedTask
243-
244-
245-
return! ValueTask.FromResult(x + y + z)
246-
}
220+
[<AutoOpen>]
221+
module TaskBuilder =
222+
open IcedTasks.TaskBase_Net10
223+
let task = TaskBuilderRuntime()

tests/IcedTasks.Tests/TaskTests_Net10.fs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@ open System
44
open Expecto
55
open System.Threading.Tasks
66
open IcedTasks
7-
// open IcedTasks.Polyfill.Task
87

9-
open IcedTasks.TaskBase_Net10
8+
open IcedTasks.Polyfill.TasksRuntime
109

1110
module TaskTests_Net10 =
1211
open System.Collections.Generic
1312

14-
let task = Testing.taskRuntime
1513

1614
let builderTests =
1715
testList "TaskBuilder" [
@@ -701,6 +699,7 @@ module TaskTests_Net10 =
701699
// TODO: Figure out why we need to wrap this in Task.Run to avoid deadlocks
702700
// Task.Run<DateTimeOffset>(fun () ->
703701
backgroundTask {
702+
// task {
704703
lock l (fun () -> l.Add(id))
705704
do! Task.yieldMany yieldTimes
706705
// do! Task.Delay(250)
@@ -806,4 +805,4 @@ module TaskTests_Net10 =
806805

807806

808807
[<Tests>]
809-
let tests = ftestList "IcedTasks.Polyfill.Task_Net10" [ builderTests ]
808+
let tests = testList "IcedTasks.Polyfill.Task_Net10" [ builderTests ]

0 commit comments

Comments
 (0)