@@ -85,16 +85,17 @@ and CancellableResumptionDynamicInfo<'TOverall> = ResumptionDynamicInfo<Cancella
8585and CancellableCode < 'TOverall , 'T > = ResumableCode< CancellableStateMachineData< 'TOverall>, 'T>
8686
8787[<Sealed>]
88- type Trampoline ( cancellationToken : CancellationToken ) =
88+ type Trampoline () =
8989
9090 let mutable bindDepth = 0
91+ let cancellationToken = FSharp.Compiler.Cancellable.Token
9192
9293 [<Literal>]
9394 static let bindDepthLimit = 100
9495
95- static let current = new ThreadLocal < Trampoline>()
96+ static let current = new AsyncLocal < Trampoline voption >()
9697
97- let delayed = System.Collections.Generic.Stack< ITrampolineInvocation>()
98+ let pending = System.Collections.Generic.Stack< ITrampolineInvocation>()
9899
99100 member this.IsCancelled = cancellationToken.IsCancellationRequested
100101
@@ -103,15 +104,13 @@ type Trampoline(cancellationToken: CancellationToken) =
103104
104105 member this.ShoudBounce = bindDepth % bindDepthLimit = 0
105106
106- static member Install ct = current.Value <- Trampoline ct
107-
108107 member val LastError : ExceptionDispatchInfo voption = ValueNone with get, set
109108
110109 member this.RunDelayed ( continuation , invocation ) =
111110 // The calling state machine is now suspended. We need to resume it next.
112- delayed .Push continuation
111+ pending .Push continuation
113112 // Schedule the delayed invocation to run.
114- delayed .Push invocation
113+ pending .Push invocation
115114
116115 member this.RunImmediate ( invocation : ITrampolineInvocation ) =
117116 bindDepth <- bindDepth + 1
@@ -121,16 +120,19 @@ type Trampoline(cancellationToken: CancellationToken) =
121120 invocation.MoveNext()
122121
123122 while not invocation.IsCompleted do
124- if delayed .Peek() .IsCompleted then
125- delayed .Pop() |> ignore
123+ if pending .Peek() .IsCompleted then
124+ pending .Pop() |> ignore
126125 else
127- delayed .Peek() .MoveNext()
126+ pending .Peek() .MoveNext()
128127 // In case this was a delayed invocation, which captures the exception, we need to replay it.
129128 invocation.ReplayExceptionIfStored()
130129 finally
131130 bindDepth <- bindDepth - 1
132131
133- static member Current = current.Value
132+ static member Current = current.Value.Value
133+
134+ static member EnsureInstalled () =
135+ if current.Value.IsNone then current.Value <- ValueSome <| Trampoline()
134136
135137type ITrampolineInvocation < 'T > =
136138 inherit ITrampolineInvocation
@@ -354,22 +356,20 @@ module CancellableAutoOpens =
354356module Cancellable =
355357 open Internal.Utilities .Library .CancellableImplementation
356358
357- let run ct ( code : Cancellable < _ >) =
358- use _ = FSharp.Compiler.Cancellable.UsingToken ct
359-
359+ let run ( code : Cancellable < _ >) =
360360 let invocation = code.GetInvocation( false )
361- Trampoline.Install ct
361+ Trampoline.EnsureInstalled ()
362362 Trampoline.Current.RunImmediate invocation
363- invocation
363+ invocation.Result
364364
365365 let runWithoutCancellation code =
366- code |> run CancellationToken.None |> _. Result
366+ use _ = FSharp.Compiler.Cancellable.UsingToken CancellationToken.None
367+ run code
367368
368369 let toAsync code =
369370 async {
370- let! ct = Async.CancellationToken
371-
372- return run ct code |> _. Result
371+ use! _holder = FSharp.Compiler.Cancellable.UseToken()
372+ return run code
373373 }
374374
375375 let token () =
0 commit comments