We track Thread objects, instead of just using
counters, because we need exclusive
locks to be reentrant, and we need to be able to upgrade share locks to exclusive.
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 18
def raw_state # :nodoc:
synchronize do
threads = @sleeping.keys | @sharing.keys | @waiting.keys
threads |= [@exclusive_thread] if @exclusive_thread
data = {}
threads.each do |thread|
purpose, compatible = @waiting[thread]
data[thread] = {
thread: thread,
sharing: @sharing[thread],
exclusive: @exclusive_thread == thread,
purpose: purpose,
compatible: compatible,
waiting: !!@waiting[thread],
sleeper: @sleeping[thread],
}
end
# NB: Yields while holding our *internal* synchronize lock,
# which is supposed to be used only for a few instructions at
# a time. This allows the caller to inspect additional state
# without things changing out from underneath, but would have
# disastrous effects upon normal operation. Fortunately, this
# method is only intended to be called when things have
# already gone wrong.
yield data
end
end