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 readNULL
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)
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