Class: QuackConcurrency::ReentrantMutex
- Inherits:
-
ConcurrencyTool
- Object
- ConcurrencyTool
- QuackConcurrency::ReentrantMutex
- Defined in:
- lib/quack_concurrency/reentrant_mutex.rb,
lib/quack_concurrency/reentrant_mutex/error.rb
Defined Under Namespace
Classes: Error
Instance Method Summary collapse
-
#initialize(duck_types: nil) ⇒ ReentrantMutex
constructor
Creates a new ReentrantMutex concurrency tool.
-
#lock ⇒ void
Locks this ReentrantMutex.
-
#locked? ⇒ Boolean
Checks if this ReentrantMutex is locked by some thread.
-
#locked_out? ⇒ Boolean
Checks if this ReentrantMutex is locked by a thread other than the caller.
-
#owned? ⇒ Boolean
Checks if this ReentrantMutex is locked by the calling thread.
-
#sleep(timeout = nil) ⇒ void
Releases the lock and sleeps.
-
#synchronize ⇒ Object
Obtains a lock, runs the block, and releases the lock when the block completes.
-
#try_lock ⇒ Boolean
Attempts to obtain the lock and returns immediately.
-
#unlock ⇒ void
Releases the lock.
Methods inherited from ConcurrencyTool
Constructor Details
#initialize(duck_types: nil) ⇒ ReentrantMutex
Creates a new QuackConcurrency::ReentrantMutex concurrency tool.
11 12 13 14 15 16 17 |
# File 'lib/quack_concurrency/reentrant_mutex.rb', line 11 def initialize(duck_types: nil) classes = setup_duck_types(duck_types) @condition_variable = classes[:condition_variable].new @mutex = classes[:mutex].new @owner = nil @lock_depth = 0 end |
Instance Method Details
#lock ⇒ void
This method returns an undefined value.
Locks this QuackConcurrency::ReentrantMutex. Will block until available.
21 22 23 24 25 26 27 28 29 |
# File 'lib/quack_concurrency/reentrant_mutex.rb', line 21 def lock @mutex.synchronize do @condition_variable.wait(@mutex) if @owner && @owner != caller raise 'internal error, invalid state' if @owner && @owner != caller @owner = caller @lock_depth += 1 end nil end |
#locked? ⇒ Boolean
Checks if this QuackConcurrency::ReentrantMutex is locked by some thread.
33 34 35 |
# File 'lib/quack_concurrency/reentrant_mutex.rb', line 33 def locked? !!@owner end |
#locked_out? ⇒ Boolean
Checks if this QuackConcurrency::ReentrantMutex is locked by a thread other than the caller.
39 40 41 |
# File 'lib/quack_concurrency/reentrant_mutex.rb', line 39 def locked_out? @mutex.synchronize { locked? && @owner != caller } end |
#owned? ⇒ Boolean
Checks if this QuackConcurrency::ReentrantMutex is locked by the calling thread.
45 46 47 |
# File 'lib/quack_concurrency/reentrant_mutex.rb', line 45 def owned? @owner == caller end |
#sleep(timeout = nil) ⇒ void
This method returns an undefined value.
Releases the lock and sleeps. When the calling thread is next woken up, it will attempt to reacquire the lock.
54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/quack_concurrency/reentrant_mutex.rb', line 54 def sleep(timeout = nil) unlock # i would rather not need to get a ducktype for sleep so we will just take # advantage of Mutex's sleep method that must take it into account already @mutex.synchronize do @mutex.sleep(timeout) end nil ensure lock unless owned? end |
#synchronize ⇒ Object
Obtains a lock, runs the block, and releases the lock when the block completes.
68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/quack_concurrency/reentrant_mutex.rb', line 68 def synchronize lock start_depth = @lock_depth start_owner = @owner result = yield result ensure unless @lock_depth == start_depth && @owner == start_owner raise Error, 'could not unlock reentrant mutex as its state has been modified' end unlock end |
#try_lock ⇒ Boolean
Attempts to obtain the lock and returns immediately.
83 84 85 86 87 88 89 90 |
# File 'lib/quack_concurrency/reentrant_mutex.rb', line 83 def try_lock @mutex.synchronize do return false if @owner && @owner != caller @owner = caller @lock_depth += 1 true end end |
#unlock ⇒ void
This method returns an undefined value.
Releases the lock.
95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/quack_concurrency/reentrant_mutex.rb', line 95 def unlock @mutex.synchronize do raise Error, 'can not unlock reentrant mutex, it is not locked' if @lock_depth == 0 raise Error, 'can not unlock reentrant mutex, caller is not the owner' unless @owner == caller @lock_depth -= 1 if @lock_depth == 0 @owner = nil @condition_variable.signal end end nil end |