Skip to content

Commit

Permalink
Provisional implementation of a variant of CancellationToken implemen…
Browse files Browse the repository at this point in the history
…tation in CE
  • Loading branch information
abelbraaksma committed Nov 5, 2023
1 parent 532ec26 commit 5a0d4e5
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 9 deletions.
51 changes: 51 additions & 0 deletions src/FSharp.Control.TaskSeq.Test/TaskSeq.Do.Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ open FsUnit
open Xunit

open FSharp.Control
open System.Threading

[<Fact>]
let ``CE taskSeq: use 'do'`` () =
Expand Down Expand Up @@ -57,6 +58,56 @@ let ``CE taskSeq: use 'do!' with a task-delay`` () =
|> verifyEmpty
|> Task.map (fun _ -> value |> should equal 2)

//module CancellationToken =
// [<Fact>]
// let ``CE taskSeq: use 'do!' with a default cancellation-token`` () =
// let mutable value = 0

// taskSeq {
// do value <- value + 1
// do! CancellationToken()
// do value <- value + 1
// }
// |> verifyEmpty
// |> Task.map (fun _ -> value |> should equal 2)

// [<Fact>]
// let ``CE taskSeq: use 'do!' with a timer cancellation-token - explicit`` () = task {
// let mutable value = 0
// use tokenSource = new CancellationTokenSource(500)

// return!
// taskSeq {
// do! tokenSource.Token // this sets the token for this taskSeq
// do value <- value + 1
// do! Task.Delay(300, tokenSource.Token)
// do! Task.Delay(300, tokenSource.Token)
// do! Task.Delay(300, tokenSource.Token)
// do value <- value + 1
// }
// |> verifyEmpty
// |> Task.map (fun _ -> value |> should equal 2)
// }


// [<Fact>]
// let ``CE taskSeq: use 'do!' with a timer cancellation-token - implicit`` () = task {
// let mutable value = 0
// use tokenSource = new CancellationTokenSource(500)

// return!
// taskSeq {
// do! tokenSource.Token // this sets the token for this taskSeq
// do value <- value + 1
// do! Task.Delay(300)
// do! Task.Delay(300)
// do! Task.Delay(300)
// do value <- value + 1
// }
// |> verifyEmpty
// |> Task.map (fun _ -> value |> should equal 2)
// }

[<Fact>]
let ``CE taskSeq: use 'do!' with Async`` () =
let mutable value = 0
Expand Down
20 changes: 15 additions & 5 deletions src/FSharp.Control.TaskSeq/TaskSeqBuilder.fs
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ module LowPriority =

else
Debug.logInfo "at TaskLike bind: await further"

sm.Data.cancellationToken.ThrowIfCancellationRequested()
sm.Data.awaiter <- awaiter
sm.Data.current <- ValueNone
false)
Expand Down Expand Up @@ -618,6 +618,10 @@ module HighPriority =
//
member inline _.Bind(task: Task<'T>, continuation: ('T -> ResumableTSC<'U>)) =
ResumableTSC<'U>(fun sm ->
// WTF???
//let x = Func<Task<_>>(fun _ -> task)
//Task<'TResult>.Run(x, sm.Data.cancellationToken)

let mutable awaiter = task.GetAwaiter()
let mutable __stack_fin = true

Expand All @@ -639,15 +643,21 @@ module HighPriority =

else
Debug.logInfo "at Bind: await further"

sm.Data.cancellationToken.ThrowIfCancellationRequested()
sm.Data.awaiter <- awaiter
sm.Data.current <- ValueNone
false)

// Binding to a cancellation token. This allows `do! someCancellationToken`
member inline _.Bind(myToken: CancellationToken, continuation: (unit -> ResumableTSC<'T>)) : ResumableTSC<'T> =
//// Binding to a cancellation token. This allows `do! someCancellationToken`
//member inline _.Bind(cancellationToken, continuation: (unit -> ResumableTSC<'T>)) : ResumableTSC<'T> =
// ResumableTSC<'T>(fun sm ->
// sm.Data.cancellationToken <- cancellationToken
// (continuation ()).Invoke(&sm))

[<CustomOperation "cancellationToken">]
member inline _.SetCancellationToken(cancellationToken, continuation: (unit -> ResumableTSC<'T>)) : ResumableTSC<'T> =
ResumableTSC<'T>(fun sm ->
sm.Data.cancellationToken <- myToken
sm.Data.cancellationToken <- cancellationToken
(continuation ()).Invoke(&sm))

member inline _.Bind(computation: Async<'T>, continuation: ('T -> ResumableTSC<'U>)) =
Expand Down
5 changes: 5 additions & 0 deletions src/FSharp.Control.TaskSeq/TaskSeqBuilder.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,8 @@ module HighPriority =

member inline Bind: task: Task<'T> * continuation: ('T -> ResumableTSC<'U>) -> ResumableTSC<'U>
member inline Bind: computation: Async<'T> * continuation: ('T -> ResumableTSC<'U>) -> ResumableTSC<'U>
//member inline Bind:
// cancellationToken: CancellationToken * continuation: (unit -> ResumableTSC<'T>) -> ResumableTSC<'T>
[<CustomOperation "cancellationToken">]
member inline SetCancellationToken:
cancellationToken: CancellationToken * continuation: (unit -> ResumableTSC<'T>) -> ResumableTSC<'T>
9 changes: 5 additions & 4 deletions src/FSharp.Control.TaskSeq/TaskSeqInternal.fs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,11 @@ module internal TaskSeqInternal =
KeyNotFoundException("The predicate function or index did not satisfy any item in the async sequence.")
|> raise

let inline withCancellationToken (cancellationToken: CancellationToken) (source: taskSeq<'T>) = taskSeq {
do! cancellationToken
yield! source
}
//let inline withCancellationToken (cancellationToken2: CancellationToken) (source: taskSeq<'T>) = taskSeq {
// // COMPILE ERROR HERE
// cancellationToken cancellationToken2
// yield! source
//}

let isEmpty (source: TaskSeq<_>) =
checkNonNull (nameof source) source
Expand Down

0 comments on commit 5a0d4e5

Please sign in to comment.