class ThreadSafe::AtomicReferenceCacheBackend::Node

before a value, but can only be used after checking value to be +!= NULL+.
deleted or created. For purposes of read-only access, a key may be read
NULL value fields indicate that a node is in the process of being
not contain user keys or values. Otherwise, keys are never nil, and
Key-value entry. Nodes with a hash field of MOVED are special, and do

def force_aquire_lock(table, i)

def force_aquire_lock(table, i)
  cheap_synchronize do
    if equal?(table.volatile_get(i)) && (hash & WAITING) == WAITING
      cheap_wait
    else
      cheap_broadcast # possibly won race vs signaller
    end
  end
end

def initialize(hash, key, value, next_node = nil)

def initialize(hash, key, value, next_node = nil)
  super()
  @key = key
  self.lazy_set_hash(hash)
  self.lazy_set_value(value)
  self.next = next_node
end

def key?(key)

def key?(key)
  @key.eql?(key)
end

def locked?

def locked?
  self.class.locked_hash?(hash)
end

def locked_hash?(hash)

def locked_hash?(hash)
  (hash & LOCKED) != 0
end

def matches?(key, hash)

def matches?(key, hash)
  pure_hash == hash && key?(key)
end

def pure_hash

def pure_hash
  hash & HASH_BITS
end

def try_await_lock(table, i)

+cheap_synchronize+ lock and perform a +cheap_broadcast+.
CAS from non-waiting +LOCKED+ state), unlockers acquire the
detecting that +WAITING+ has been set when unlocking lock (via a failed
The corresponding signalling operation is performed within callers: Upon

available upon exit, which enables these simple single-wait mechanics.
still set. It is OK for this method to return even if lock is not
and then sets +WAITING+ bits on hash field and blocks (once) if they are
Spins a while if +LOCKED+ bit set and this node is the first of its bin,
def try_await_lock(table, i)
  if table && i >= 0 && i < table.size # bounds check, TODO: why are we bounds checking?
    spins = SPIN_LOCK_ATTEMPTS
    randomizer = base_randomizer = Util::XorShiftRandom.get
    while equal?(table.volatile_get(i)) && self.class.locked_hash?(my_hash = hash)
      if spins >= 0
        if (randomizer = (randomizer >> 1)).even? # spin at random
          if (spins -= 1) == 0
            Thread.pass # yield before blocking
          else
            randomizer = base_randomizer = Util::XorShiftRandom.xorshift(base_randomizer) if randomizer.zero?
          end
        end
      elsif cas_hash(my_hash, my_hash | WAITING)
        force_aquire_lock(table, i)
        break
      end
    end
  end
end

def try_lock_via_hash(node_hash = hash)

def try_lock_via_hash(node_hash = hash)
  if cas_hash(node_hash, locked_hash = node_hash | LOCKED)
    begin
      yield
    ensure
      unlock_via_hash(locked_hash, node_hash)
    end
  end
end

def unlock_via_hash(locked_hash, node_hash)

def unlock_via_hash(locked_hash, node_hash)
  unless cas_hash(locked_hash, node_hash)
    self.hash = node_hash
    cheap_synchronize { cheap_broadcast }
  end
end