@@ -153,6 +153,57 @@ type IndexNode =
153153 end
154154
155155#if ! FABLE_ COMPILER
156+
157+ type internal AsyncBlockingCollection < 'a >() =
158+ let store = System.Collections.Generic.Queue< 'a>()
159+
160+ let mutable next : option < Tasks.TaskCompletionSource < unit >> = None //Tasks.TaskCompletionSource<unit>()
161+
162+ member x.Add ( value : 'a ) =
163+ lock store ( fun () ->
164+ store.Enqueue value
165+ match next with
166+ | Some n ->
167+ n.SetResult()
168+ next <- None
169+ | None ->
170+ ()
171+ )
172+
173+ member x.Take () =
174+ Async.FromContinuations ( fun ( success , error , cancel ) ->
175+ Monitor.Enter store
176+ try
177+ if store.Count > 0 then
178+ let value = store.Dequeue()
179+ Monitor.Exit store
180+ success value
181+ else
182+ let tcs =
183+ match next with
184+ | Some n -> n
185+ | None ->
186+ let n = Tasks.TaskCompletionSource< unit>()
187+ next <- Some n
188+ n
189+ Monitor.Exit store
190+ tcs.Task.ContinueWith ( fun ( _t : Tasks.Task < unit >) ->
191+ Async.StartWithContinuations( x.Take(), success, error, cancel)
192+ ) |> ignore
193+ with
194+ | :? OperationCanceledException as e ->
195+ Monitor.Exit store
196+ cancel e
197+ | e ->
198+ Monitor.Exit store
199+ error e
200+ )
201+
202+ member x.Clear () =
203+ lock store ( fun () ->
204+ store.Clear()
205+ )
206+
156207/// datastructure representing an abstract index.
157208/// supported operations are: Index.zero, Index.after(index), Index.before(index), Index.between(l, r).
158209/// this is a 'simple' solution to the order-maintenance problem that has insert in O(log N), delete in O(1) and compare in O(1).
@@ -161,21 +212,16 @@ type IndexNode =
161212type Index private ( real : IndexNode ) =
162213 do real.AddRef()
163214
164- /// we create a thread for deleting the underlying values when Index goes out of scope.
165- /// this way we avoid blocking the finalizer for Index.
166- static let startThread ( run : unit -> unit ) =
167- let start = System.Threading.ThreadStart( run)
168- let thread = System.Threading.Thread( start, IsBackground = true , Name = " Index cleanup thread" )
169- thread.Start()
170- thread
171-
172- static let queue = new System.Collections.Concurrent.BlockingCollection< IndexNode>()
173- static let runner =
174- startThread ( fun () ->
215+
216+ static let queue = new AsyncBlockingCollection< IndexNode>()
217+
218+ static do
219+ async {
175220 while true do
176- try queue.Take() .Delete()
177- with e -> printfn " Index cleanup thread failed with: %A " e
178- )
221+ let! v = queue.Take()
222+ do ! Async.SwitchToThreadPool()
223+ v.Delete()
224+ } |> Async.Start
179225
180226 member private x.Value = real
181227
0 commit comments