提交 acafb503 编写于 作者: F Fraser Waters 提交者: Kevin Ransom (msft)

Fix LinkedSubSource leak in Async.Choice (#7892)

* Fix LinkedSubSource leak in Async.Choice

* ref -> mutable
上级 cab05203
......@@ -1293,35 +1293,54 @@ namespace Microsoft.FSharp.Control
| Choice1Of2 computations ->
ProtectedCode ctxt (fun ctxt ->
let ctxtWithSync = DelimitSyncContext ctxt
let noneCount = ref 0
let exnCount = ref 0
let mutable count = computations.Length
let mutable noneCount = 0
let mutable someOrExnCount = 0
let innerCts = new LinkedSubSource(ctxtWithSync.token)
let scont (result: 'T option) =
match result with
| Some _ ->
if Interlocked.Increment exnCount = 1 then
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.cont result)
let result =
match result with
| Some _ ->
if Interlocked.Increment &someOrExnCount = 1 then
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.cont result)
else
fake()
| None ->
if Interlocked.Increment &noneCount = computations.Length then
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.cont None)
else
fake()
if Interlocked.Decrement &count = 0 then
innerCts.Dispose()
result
let econt (exn: ExceptionDispatchInfo) =
let result =
if Interlocked.Increment &someOrExnCount = 1 then
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.econt exn)
else
fake()
| None ->
if Interlocked.Increment noneCount = computations.Length then
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.cont None)
if Interlocked.Decrement &count = 0 then
innerCts.Dispose()
result
let ccont (exn: OperationCanceledException) =
let result =
if Interlocked.Increment &someOrExnCount = 1 then
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.ccont exn)
else
fake()
let econt (exn: ExceptionDispatchInfo) =
if Interlocked.Increment exnCount = 1 then
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.econt exn)
else
fake()
if Interlocked.Decrement &count = 0 then
innerCts.Dispose()
let ccont (exn: OperationCanceledException) =
if Interlocked.Increment exnCount = 1 then
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.ccont exn)
else
fake()
result
for c in computations do
QueueAsync innerCts.Token scont econt ccont c |> unfake
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册