@@ -72,7 +72,7 @@ type ITrampolineInvocation =
7272type CancellableStateMachineData < 'T > =
7373
7474 [<DefaultValue( false ) >]
75- val mutable Result : 'T
75+ val mutable Result : Result < 'T , ExceptionDispatchInfo >
7676
7777and CancellableStateMachine < 'TOverall > = ResumableStateMachine< CancellableStateMachineData< 'TOverall>>
7878and ICancellableStateMachine < 'TOverall > = IResumableStateMachine< CancellableStateMachineData< 'TOverall>>
@@ -84,7 +84,7 @@ and CancellableCode<'TOverall, 'T> = ResumableCode<CancellableStateMachineData<'
8484type Trampoline ( cancellationToken : CancellationToken ) =
8585 let mutable bindDepth = 0
8686
87- let stack = Collections.Generic.Stack< ITrampolineInvocation>()
87+ let stack = System. Collections.Generic.Stack< ITrampolineInvocation>()
8888
8989 static let current = new ThreadLocal< Trampoline>()
9090
@@ -99,6 +99,8 @@ type Trampoline(cancellationToken: CancellationToken) =
9999
100100 member _.Set ( invocation ) = stack.Push( invocation)
101101
102+ member val ExceptionMap = ConditionalWeakTable< exn, ExceptionDispatchInfo>()
103+
102104 [<DebuggerHidden>]
103105 member this.Execute ( invocation ) =
104106 bindDepth <- bindDepth + 1
@@ -119,24 +121,44 @@ type ITrampolineInvocation<'T> =
119121 inherit ITrampolineInvocation
120122 abstract Result: 'T
121123
124+ [<AutoOpen>]
125+ module ExceptionDispatchInfoHelpers =
126+ type ExceptionDispatchInfo with
127+ member edi.ThrowAny () =
128+ edi.Throw()
129+ Unchecked.defaultof<_>
130+
131+ static member RestoreOrCapture ( exn : exn ) =
132+ match Trampoline.Current.ExceptionMap.TryGetValue exn with
133+ | true , edi -> edi
134+ | _ ->
135+ let edi = ExceptionDispatchInfo.Capture exn
136+ Trampoline.Current.ExceptionMap.Add( exn, edi)
137+ edi
138+
139+ [<NoEquality; NoComparison>]
122140type ICancellableInvokable < 'T > =
123141 abstract Create: unit -> ITrampolineInvocation < 'T >
124142
125143[<NoEquality; NoComparison>]
126144type CancellableInvocation < 'T , 'Machine when 'Machine :> IAsyncStateMachine and 'Machine :> ICancellableStateMachine < 'T >>( machine : 'Machine )
127145 =
128-
129146 let mutable machine = machine
130147
131148 interface ITrampolineInvocation< 'T> with
132- member _.MoveNext () = machine.MoveNext()
149+ member this.MoveNext () = machine.MoveNext()
150+
151+ member _.Result =
152+ match machine.Data.Result with
153+ | Ok value -> value
154+ | Error edi -> edi.ThrowAny()
155+
133156 member _.IsCompleted = machine.ResumptionPoint = - 1
134- member _.Result = machine.Data.Result
135157
136158 interface ICancellableInvokable< 'T> with
137159 member _.Create () = CancellableInvocation<_, _>( machine)
138160
139- [<Struct; NoComparison>]
161+ [<Struct; NoComparison; NoEquality >]
140162type Cancellable < 'T >( invokable : ICancellableInvokable < 'T >) =
141163
142164 member _.GetInvocation () = invokable.Create()
@@ -166,7 +188,7 @@ type CancellableBuilder() =
166188
167189 member inline _.Return ( value : 'T ) : CancellableCode < 'T , 'T > =
168190 CancellableCode< 'T, _>( fun sm ->
169- sm.Data.Result <- value
191+ sm.Data.Result <- Ok value
170192 true )
171193
172194 member inline _.Combine
@@ -237,7 +259,6 @@ type CancellableBuilder() =
237259 else
238260 Trampoline.Current.Execute invocation
239261 ( continuation invocation.Result) .Invoke(& sm))
240- |> throwIfCancellationRequested
241262
242263 member inline this.ReturnFrom ( comp : Cancellable < 'T >) : CancellableCode < 'T , 'T > = this.Bind( comp, this.Return)
243264
@@ -247,10 +268,15 @@ type CancellableBuilder() =
247268
248269 ( MoveNextMethodImpl<_>( fun sm ->
249270 __ resumeAt sm.ResumptionPoint
250- let __stack_code_fin = code.Invoke(& sm)
251271
252- if __ stack_ code_ fin then
253- sm.ResumptionPoint <- - 1 ))
272+ try
273+ let __stack_code_fin = code.Invoke(& sm)
274+
275+ if __ stack_ code_ fin then
276+ sm.ResumptionPoint <- - 1
277+ with exn ->
278+ sm.ResumptionPoint <- - 1
279+ sm.Data.Result <- Error <| ExceptionDispatchInfo.RestoreOrCapture exn))
254280
255281 ( SetStateMachineMethodImpl<_>( fun _ _ -> ()))
256282
@@ -263,8 +289,12 @@ type CancellableBuilder() =
263289 let resumptionInfo =
264290 { new CancellableResumptionDynamicInfo<_>( initialResumptionFunc) with
265291 member info.MoveNext ( sm ) =
266- if info.ResumptionFunc.Invoke(& sm) then
292+ try
293+ if info.ResumptionFunc.Invoke(& sm) then
294+ sm.ResumptionPoint <- - 1
295+ with exn ->
267296 sm.ResumptionPoint <- - 1
297+ sm.Data.Result <- Error <| ExceptionDispatchInfo.RestoreOrCapture exn
268298
269299 member _.SetStateMachine ( _ , _ ) = ()
270300 }
0 commit comments