class Concurrent::ReentrantReadWriteLock
def acquire_write_lock
-
(Concurrent::ResourceLimitError)
- if the maximum number of writers
Returns:
-
(Boolean)
- true if the lock is successfully acquired
def acquire_write_lock if (held = @HeldCount.value) >= WRITE_LOCK_HELD # if we already have a write (exclusive) lock, there's no need to wait @HeldCount.value = held + WRITE_LOCK_HELD return true end while true c = @Counter.value raise ResourceLimitError.new('Too many writer threads') if max_writers?(c) # To go ahead and take the lock without waiting, there must be no writer # running right now, AND no writers who came before us still waiting to # acquire the lock # Additionally, if any read locks have been taken, we must hold all of them if held > 0 && @Counter.compare_and_set(1, c+RUNNING_WRITER) # If we are the only one reader and successfully swap the RUNNING_WRITER bit on, then we can go ahead @HeldCount.value = held + WRITE_LOCK_HELD return true elsif @Counter.compare_and_set(c, c+WAITING_WRITER) while true # Now we have successfully incremented, so no more readers will be able to increment # (they will wait instead) # However, readers OR writers could decrement right here @WriteQueue.synchronize do # So we have to do another check inside the synchronized section # If a writer OR another reader is running, then go to sleep c = @Counter.value @WriteQueue.ns_wait if running_writer?(c) || running_readers(c) != held end # Note: if you are thinking of replacing the above 'synchronize' block # with #wait_until, read the comment in #acquire_read_lock first! # We just came out of a wait # If we successfully turn the RUNNING_WRITER bit on with an atomic swap, # then we are OK to stop waiting and go ahead # Otherwise go back and wait again c = @Counter.value if !running_writer?(c) && running_readers(c) == held && @Counter.compare_and_set(c, c+RUNNING_WRITER-WAITING_WRITER) @HeldCount.value = held + WRITE_LOCK_HELD return true end end end end end