anchor.diff:          exitWriteLockIf &this.locker true
   
   
  -    member this.SyncRoot 
  +    member internal this.SyncRoot with get() = c :> obj
  +
  +    member internal this.Comparer with get() = lock(c) (fun _ -> c.Value.Comparer)
  +    member internal this.IsEmpty = lock(c) (fun _ -> not (c.Value.MoveFirst()))
  +
  +    member internal this.First 
         with get() = 
  -        if this.syncRoot = null then Interlocked.CompareExchange<obj>(&this.syncRoot, new Object(), null) |> ignore
  -        this.syncRoot
  -
  -    member this.Comparer with get() = c.Value.Comparer
  -    member this.IsEmpty = not (c.Value.MoveFirst())
  -
  -    member this.First 
  -      with get() = 
  -        if c.Value.MoveFirst() then c.Value.Current else invalidOp "Series is empty"
  -
  -    member this.Last 
  +        let entered = enterLockIf c true
  +        try
  +          if c.Value.MoveFirst() then c.Value.Current else invalidOp "Series is empty"
  +        finally
  +          exitLockIf c entered
  +
  +    member internal this.Last 
         with get() =
  -        if c.Value.MoveLast() then c.Value.Current else invalidOp "Series is empty"
  -
  -    member this.TryFind(k:'K, direction:Lookup, [<Out>] result: byref<KeyValuePair<'K, 'V>>) = 
  -      if c.Value.MoveAt(k, direction) then
  -        result <- c.Value.Current 
  -        true
  -      else false
  -
  -    member this.TryGetFirst([<Out>] res: byref<KeyValuePair<'K, 'V>>) = 
  -      if c.Value.MoveFirst() then
  -        res <- c.Value.Current
  -        true
  -      else false
  -
  -    member this.TryGetLast([<Out>] res: byref<KeyValuePair<'K, 'V>>) = 
  -      if c.Value.MoveLast() then
  -        res <- c.Value.Current
  -        true
  -      else false
  -
  -    member this.TryGetValue(k, [<Out>] value:byref<'V>) = 
  -      if c.Value.IsContinuous then
  -        c.Value.TryGetValue(k, &value)
  -      else
  -        let ok = c.Value.MoveAt(k, Lookup.EQ)
  -        if ok then value <- c.Value.CurrentValue else value <- Unchecked.defaultof<'V>
  -        ok
  -
  -    member this.Item 
  -      with get k = 
  -        if c.Value.MoveAt(k, Lookup.EQ) then c.Value.CurrentValue
  -        else raise (KeyNotFoundException())
  -
  -    member this.Keys 
  +        let entered = enterLockIf c true
  +        try
  +          if c.Value.MoveLast() then c.Value.Current else invalidOp "Series is empty"
  +        finally
  +          exitLockIf c entered
  +
  +    member internal this.TryFind(k:'K, direction:Lookup, [<Out>] result: byref<KeyValuePair<'K, 'V>>) = 
  +      let entered = enterLockIf c true
  +      try
  +        if c.Value.MoveAt(k, direction) then
  +          result <- c.Value.Current 
  +          true
  +        else false
  +      finally
  +        exitLockIf c entered
  +
  +    member internal this.TryGetFirst([<Out>] res: byref<KeyValuePair<'K, 'V>>) = 
  +      let entered = enterLockIf c true
  +      try
  +        if c.Value.MoveFirst() then
  +          res <- c.Value.Current
  +          true
  +        else false
  +      finally
  +        exitLockIf c entered
  +
  +    member internal this.TryGetLast([<Out>] res: byref<KeyValuePair<'K, 'V>>) =
  +      let entered = enterLockIf c true
  +      try
  +        if c.Value.MoveLast() then
  +          res <- c.Value.Current
  +          true
  +        else false
  +      finally
  +        exitLockIf c entered
  +
  +    member internal this.TryGetValue(k, [<Out>] value:byref<'V>) =
  +      let entered = enterLockIf c true
  +      try
  +        if c.Value.IsContinuous then
  +          c.Value.TryGetValue(k, &value)
  +        else
  +          let ok = c.Value.MoveAt(k, Lookup.EQ)
  +          if ok then value <- c.Value.CurrentValue else value <- Unchecked.defaultof<'V>
  +          ok
  +      finally
  +        exitLockIf c entered
  +
  +    member internal this.Item 
  +      with get k =
  +        let entered = enterLockIf c true
  +        try
  +          if c.Value.MoveAt(k, Lookup.EQ) then c.Value.CurrentValue
  +          else raise (KeyNotFoundException())
  +        finally
  +        exitLockIf c entered
  +
  +    member internal this.Keys 
         with get() =
  -        let c = this.GetCursor()
  +        // TODO manual impl, seq is slow
  +        use c = this.GetCursor()
           seq {
             while c.MoveNext() do
               yield c.CurrentKey
           }
   
  -    member this.Values
  +    member internal this.Values
         with get() =
  -        let c = this.GetCursor()
  +        // TODO manual impl, seq is slow
  +        use c = this.GetCursor()
           seq {
             while c.MoveNext() do
               yield c.CurrentValue
           }
   
  -//    override x.Finalize() =
  -//      try
  -//        for v in c.Values do
  -//          try
  -//            v.Dispose()
  -//          with
  -//          | :? ObjectDisposedException -> ()
  -//        c.Dispose()
  -//      with
  -//      | :? ObjectDisposedException -> ()
  -      
  +    override x.Finalize() = if c.IsValueCreated then c.Value.Dispose()
   
       interface IEnumerable<KeyValuePair<'K, 'V>> with
         member this.GetEnumerator() = this.GetCursor() :> IEnumerator<KeyValuePair<'K, 'V>>
  
positive.code:                 cursor.Dispose()
                  new BatchMapValuesCursor<_,_,_>(cursorFactory, f2) :> ICursor<_,_>
                ) :> Series<_,_>
  
  
  
  and
  
negative.code:       member this.SyncRoot with get() = this.SyncRoot
  
        member this.IsEmpty = this.IsEmpty
        member this.First with get() = this.First 
        member this.Last with get() = this.Last
        member this.TryFind(k:'K, direction:Lookup, [<Out>] result: byref<KeyValuePair<'K, 'V>>) = this.TryFind(k, direction, &result)
  