Method: ThreadSafe::AtomicReferenceCacheBackend::Node#try_await_lock
- Defined in:
- lib/thread_safe/atomic_reference_cache_backend.rb
#try_await_lock(table, i) ⇒ Object
Spins a while if +LOCKED+ bit set and this node is the first of its bin, and then sets +WAITING+ bits on hash field and blocks (once) if they are still set. It is OK for this method to return even if lock is not available upon exit, which enables these simple single-wait mechanics.
The corresponding signalling operation is performed within callers: Upon detecting that +WAITING+ has been set when unlocking lock (via a failed CAS from non-waiting +LOCKED+ state), unlockers acquire the +cheap_synchronize+ lock and perform a +cheap_broadcast+.
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/thread_safe/atomic_reference_cache_backend.rb', line 260 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 |