anchor.diff:          let version = if doSpin then Volatile.Read(&this.source.version) else this.source.orderVersion
           result <-
           /////////// Start read-locked code /////////////
  -          let res =
  -            if this.source.ChunkUpperLimit = 0 then
  -              let hash = this.source.Hasher.Hash(key)
  -              let c = 
  -                if not this.HasValidInner then 2 // <> 0 below
  -                else this.source.Comparer.Compare(hash, this.outerCursor.CurrentKey)
  +          let mutable entered = false
  +          try
  +            entered <- enterWriteLockIf &this.source.locker this.source.isSynchronized
  +            newInner <- this.innerCursor
  +            let res =
  +              if this.source.ChunkUpperLimit = 0 then
  +                let hash = this.source.Hasher.Hash(key)
  +                let c = 
  +                  if not this.HasValidInner then 2 // <> 0 below
  +                  else this.source.Comparer.Compare(hash, this.outerCursor.CurrentKey)
                 
  -              if c <> 0 then // not in the current bucket, switch bucket
  -                if this.outerCursor.MoveAt(hash, Lookup.EQ) then // Equal!
  +                if c <> 0 then // not in the current bucket, switch bucket
  +                  if this.outerCursor.MoveAt(hash, Lookup.EQ) then // Equal!
  +                    newInner <- new SortedMapCursor<'K,'V>(this.outerCursor.CurrentValue)
  +                    newInner.MoveAt(key, direction)
  +                  else
  +                    false
  +                else
  +                  newInner.MoveAt(key, direction)
  +              else
  +                if this.outerCursor.MoveAt(key, Lookup.LE) then // LE!
                     newInner <- new SortedMapCursor<'K,'V>(this.outerCursor.CurrentValue)
                     newInner.MoveAt(key, direction)
                   else
                     false
  -              else
  -                newInner.MoveAt(key, direction)
  +
  +            if res then
  +              this.isBatch <- false
  +              true
               else
  -              if this.outerCursor.MoveAt(key, Lookup.LE) then // LE!
  -                newInner <- new SortedMapCursor<'K,'V>(this.outerCursor.CurrentValue)
  -                newInner.MoveAt(key, direction)
  -              else
  -                false
  -
  -          if res then
  -            this.isBatch <- false
  -            true
  -          else
  -              match direction with
  -              | Lookup.LT | Lookup.LE ->
  -                // look into previous bucket
  -                if this.outerCursor.MovePrevious() then
  -                  newInner <- new SortedMapCursor<'K,'V>(this.outerCursor.CurrentValue)
  -                  let res = newInner.MoveAt(key, direction)
  -                  if res then
  -                    this.isBatch <- false
  -                    true
  +                match direction with
  +                | Lookup.LT | Lookup.LE ->
  +                  // look into previous bucket
  +                  if this.outerCursor.MovePrevious() then
  +                    newInner <- new SortedMapCursor<'K,'V>(this.outerCursor.CurrentValue)
  +                    let res = newInner.MoveAt(key, direction)
  +                    if res then
  +                      this.isBatch <- false
  +                      true
  +                    else
  +                      this.Reset()
  +                      false
                     else
                       this.Reset()
                       false
  -                else
  -                  this.Reset()
  -                  false
  -              | Lookup.GT | Lookup.GE ->
  -                // look into next bucket
  -                let moved = this.outerCursor.MoveNext() 
  -                if moved then
  -                  newInner <- new SortedMapCursor<'K,'V>(this.outerCursor.CurrentValue)
  -                  let res = newInner.MoveAt(key, direction)
  -                  if res then
  -                    this.isBatch <- false
  -                    true
  +                | Lookup.GT | Lookup.GE ->
  +                  // look into next bucket
  +                  let moved = this.outerCursor.MoveNext() 
  +                  if moved then
  +                    newInner <- new SortedMapCursor<'K,'V>(this.outerCursor.CurrentValue)
  +                    let res = newInner.MoveAt(key, direction)
  +                    if res then
  +                      this.isBatch <- false
  +                      true
  +                    else
  +                      this.Reset()
  +                      false 
                     else
                       this.Reset()
  -                    false 
  -                else
  -                  this.Reset()
  -                  false
  -              | _ -> false // LookupDirection.EQ
  +                    false
  +                | _ -> false // LookupDirection.EQ
  +          finally
  +            exitWriteLockIf &this.source.locker entered
         /////////// End read-locked code /////////////
           if doSpin then
             let nextVersion = Volatile.Read(&this.source.nextVersion)
  
positive.code:         result <-
          /////////// Start read-locked code /////////////
            try
              if this.isBatch then
                raise (NotImplementedException("TODO test & review"))
                this.isBatch <- false
                newInner <- new SortedMapCursor<'K,'V>(this.outerCursor.CurrentValue)
                newInner.MoveLast() |> ignore
  
              if not this.HasValidInner then
                if this.outerCursor.MoveLast() then
                  newInner <- new SortedMapCursor<'K,'V>(this.outerCursor.CurrentValue)
                  newInner.MoveLast()
                else false
              else
                if this.HasValidInner && newInner.MovePrevious() then true
                else
                  if this.outerCursor.MovePrevious() then
                    this.isBatch <- false
                    newInner <- new SortedMapCursor<'K,'V>(this.outerCursor.CurrentValue)
                    newInner.MovePrevious()
                  else false
            with
            | :? OutOfOrderKeyException<'K> as ooex ->
               raise (new OutOfOrderKeyException<'K>((if this.isBatch then this.outerCursor.CurrentValue.Last.Key else this.innerCursor.CurrentKey), "SortedMap order was changed since last move. Catch OutOfOrderKeyException and use its CurrentKey property together with MoveAt(key, Lookup.GT) to recover."))
  
negative.code:           else sw.SpinOnce()
        if result then
          //if this.HasValidInner then this.innerCursor.Dispose()
          if doSwitchInner then this.innerCursor <- newInner
        result
  
      member this.MoveFirst() =
  