Class: QuackConcurrency::Mutex
- Inherits:
-
Object
- Object
- QuackConcurrency::Mutex
- Defined in:
- lib/quack_concurrency/mutex.rb
Overview
Direct Known Subclasses
Instance Method Summary collapse
-
#initialize ⇒ Mutex
constructor
Creates a new Mutex concurrency tool.
- #lock(&block) ⇒ Object
-
#locked? ⇒ Boolean
Checks if it is locked by a thread.
-
#locked_out? ⇒ Boolean
Checks if it is locked by another thread.
-
#owned? ⇒ Boolean
Checks if it is locked by current thread.
-
#owner ⇒ nil, Thread
Returns the thread locking it if one exists.
-
#sleep(timeout = nil) ⇒ Integer
Releases the lock and puts this thread to sleep.
-
#synchronize(&block) ⇒ Object
Obtains the lock or blocks until the lock is available.
-
#try_lock ⇒ Boolean
Attempts to obtain the lock and return immediately.
- #unlock(&block) ⇒ Object
-
#waiting_threads_count ⇒ Integer
Returns the number of threads currently waiting on it.
Constructor Details
#initialize ⇒ Mutex
Creates a new QuackConcurrency::Mutex concurrency tool.
12 13 14 15 16 |
# File 'lib/quack_concurrency/mutex.rb', line 12 def initialize @condition_variable = SafeConditionVariable.new @mutex = ::Mutex.new @owner = nil end |
Instance Method Details
#lock ⇒ void #lock { ... } ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/quack_concurrency/mutex.rb', line 27 def lock(&block) raise ThreadError, 'Attempt to lock a mutex which is already locked by this thread' if owned? if block_given? lock begin yield ensure unlock end else @mutex.synchronize do @condition_variable.wait(@mutex) if locked? @owner = caller end nil end end |
#locked? ⇒ Boolean
Checks if it is locked by a thread.
47 48 49 |
# File 'lib/quack_concurrency/mutex.rb', line 47 def locked? !!@owner end |
#locked_out? ⇒ Boolean
Checks if it is locked by another thread.
53 54 55 56 |
# File 'lib/quack_concurrency/mutex.rb', line 53 def locked_out? # don't need a mutex because we know #owned? can't change during the call locked? && !owned? end |
#owned? ⇒ Boolean
Checks if it is locked by current thread.
60 61 62 |
# File 'lib/quack_concurrency/mutex.rb', line 60 def owned? @owner == caller end |
#owner ⇒ nil, Thread
Returns the thread locking it if one exists.
66 67 68 |
# File 'lib/quack_concurrency/mutex.rb', line 66 def owner @owner end |
#sleep(timeout = nil) ⇒ Integer
Releases the lock and puts this thread to sleep.
75 76 77 78 79 80 81 82 83 84 |
# File 'lib/quack_concurrency/mutex.rb', line 75 def sleep(timeout = nil) validate_timeout(timeout) unlock do if timeout == nil || timeout == Float::INFINITY elapsed_time = (timer { Thread.stop }).round else elapsed_time = Kernel.sleep(timeout) end end end |
#synchronize(&block) ⇒ Object
Obtains the lock or blocks until the lock is available.
91 92 93 94 |
# File 'lib/quack_concurrency/mutex.rb', line 91 def synchronize(&block) raise ThreadError, 'must be called with a block' unless block_given? lock(&block) end |
#try_lock ⇒ Boolean
Attempts to obtain the lock and return immediately.
99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/quack_concurrency/mutex.rb', line 99 def try_lock raise ThreadError, 'Attempt to lock a mutex which is already locked by this thread' if owned? @mutex.synchronize do if locked? false else @owner = caller true end end end |
#unlock ⇒ void #unlock { ... } ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/quack_concurrency/mutex.rb', line 121 def unlock(&block) if block_given? temporarily_release(&block) else @mutex.synchronize do ensure_can_unlock if @condition_variable.any_waiting_threads? @condition_variable.signal # we do this to avoid a bug # consider this problem, imagine we have three threads: # * A: this thread # * B: has previously called #lock and is waiting on the @condition_variable # * C: enters #lock after A has released the lock but before B has reacquired it # is this scenario the threads may end up executing not in the chronological order # that they entered #lock @owner = true else @owner = nil end end nil end end |
#waiting_threads_count ⇒ Integer
Returns the number of threads currently waiting on it.
148 149 150 |
# File 'lib/quack_concurrency/mutex.rb', line 148 def waiting_threads_count @condition_variable.waiting_threads_count end |