@@ -291,6 +291,7 @@ module CollectionExtensions =
291291 let mutable initial = true
292292 let reader = list.GetReader() // NOTE: need to be held, otherwise it will be collected and no updates can be consumed
293293 let cache = System.Collections.Generic.Dictionary< struct ( IIndexListReader< 'T> * FSharp.Data.Adaptive.Index), struct ( 'T * IIndexListReader< 'T>)>() // TODO: refcounting
294+ let removedDirty = DefaultHashSet.create< IIndexListReader< 'T>>()
294295
295296 member x.Invoke ( token : AdaptiveToken , r : IIndexListReader < 'T >, i : FSharp.Data.Adaptive.Index , n : 'T ) =
296297 let mutable delta = HashSetDelta.empty
@@ -316,8 +317,15 @@ module CollectionExtensions =
316317 let mutable delta = HashSetDelta.empty
317318 match cache.TryGetValue ( struct ( r, i)) with
318319 | ( true , struct ( n, subReader)) ->
319- cache.Remove ( struct ( r, i)) |> ignore
320- subReader.Outputs.Remove x |> ignore
320+ if not ( cache.Remove ( struct ( r, i))) then
321+ unexpected()
322+
323+ // if subReader is outOfDate it is expected to be also included in "dirty" inputs
324+ // -> prevent updates to be included in delta computation
325+ if subReader.OutOfDate then
326+ removedDirty.Add( subReader) |> ignore
327+ elif not ( subReader.Outputs.Remove x) then
328+ unexpected()
321329
322330 delta <- delta.Add ( Rem n)
323331 subReader.State |> IndexList.iteri ( fun i old ->
@@ -338,12 +346,15 @@ module CollectionExtensions =
338346 | _ -> unexpected()
339347
340348 for d in dirty do
341- let inner = d.GetChanges token
342- for c in inner do
343- match c with
344- | ( i, Set n) -> delta <- delta.Combine ( x.Invoke( token, d, i, n))
345- | ( i, Remove) -> delta <- delta.Combine ( x.Revoke( d, i))
349+ if not ( removedDirty.Contains d) then
350+ let inner = d.GetChanges token
351+ for c in inner do
352+ match c with
353+ | ( i, Set n) -> delta <- delta.Combine ( x.Invoke( token, d, i, n))
354+ | ( i, Remove) -> delta <- delta.Combine ( x.Revoke( d, i))
346355
356+ removedDirty.Clear()
357+
347358 delta
348359
349360
@@ -355,18 +366,19 @@ module CollectionExtensions =
355366 let mutable initial = true
356367 let reader = set.GetReader() // NOTE: need to be held, otherwise it will be collected and no updates can be consumed
357368 let cache = DefaultDictionary.create< 'T, struct ( IHashSetReader< 'T> * ref< int>)>()
369+ let removedDirty = DefaultHashSet.create< IHashSetReader< 'T>>()
358370
359371 member x.Invoke ( token : AdaptiveToken , n : 'T ) =
360372 let mutable delta = HashSetDelta.empty
361373 match cache.TryGetValue n with
362374 | ( true , (_, refCount)) -> refCount.Value <- refCount.Value + 1
363375 | _ ->
364376 let subNodes = getChildren n
365- let reader = subNodes.GetReader()
366- cache[ n] <- ( reader , ref 1 )
377+ let subReader = subNodes.GetReader()
378+ cache[ n] <- ( subReader , ref 1 )
367379
368380 delta <- delta.Add ( Add n)
369- let content = reader .GetChanges token
381+ let content = subReader .GetChanges token
370382 for c in content do
371383 if c.Count <> 1 then unexpected()
372384 delta <- delta.Combine ( x.Invoke( token, c.Value))
@@ -376,13 +388,20 @@ module CollectionExtensions =
376388 member x.Revoke ( n : 'T ) =
377389 let mutable delta = HashSetDelta.empty
378390 match cache.TryGetValue n with
379- | ( true , ( reader , refCount)) ->
391+ | ( true , ( subReader , refCount)) ->
380392 if refCount.Value = 1 then
381- cache.Remove n |> ignore
382- reader.Outputs.Remove x |> ignore
393+ if not ( cache.Remove n) then
394+ unexpected()
395+
396+ // if subReader is outOfDate it is expected to be also included in "dirty" inputs
397+ // -> prevent updates to be included in delta computation
398+ if subReader.OutOfDate then
399+ removedDirty.Add( subReader) |> ignore
400+ elif not ( subReader.Outputs.Remove x) then
401+ unexpected()
383402
384403 delta <- delta.Add ( Rem n)
385- for old in reader .State do
404+ for old in subReader .State do
386405 delta <- delta.Combine ( x.Revoke( old))
387406 else
388407 refCount.Value <- refCount.Value - 1
@@ -404,13 +423,17 @@ module CollectionExtensions =
404423 HashSetDelta.empty
405424
406425 for d in dirty do
407- let inner = d.GetChanges token |> HashSetDelta.collect ( fun d ->
408- let n = d.Value
409- if d.Count = 1 then x.Invoke( token, n)
410- elif d.Count = - 1 then x.Revoke( n)
411- else unexpected()
412- )
413- deltas <- deltas.Combine inner
426+ if not ( removedDirty.Contains d) then
427+ let inner = d.GetChanges token |> HashSetDelta.collect ( fun d ->
428+ let n = d.Value
429+ if d.Count = 1 then x.Invoke( token, n)
430+ elif d.Count = - 1 then x.Revoke( n)
431+ else unexpected()
432+ )
433+ deltas <- deltas.Combine inner
434+
435+ removedDirty.Clear()
436+
414437 deltas
415438
416439
0 commit comments