Class: ProcessShared::Mutex
- Inherits:
-
Object
- Object
- ProcessShared::Mutex
- Defined in:
- lib/process_shared/mutex.rb
Overview
This Mutex class is implemented as a Semaphore with a second internal Semaphore used to track the locking process is tracked. ProcessError is raised if either #unlock is called by a process different from the locking process, or if #lock is called while the process already holds the lock (i.e. the mutex is not re-entrant). This tracking is not without performance cost, of course (current implementation uses the additional Semaphore and SharedMemory segment).
The API is intended to be identical to the Mutex in the core Ruby library.
TODO: the core Ruby api has no #close method, but this Mutex must release its Semaphore and SharedMemory resources. For now, rely on the object finalizers of those objects…
Instance Method Summary collapse
-
#initialize ⇒ Mutex
constructor
def self.open(&block) new.with_self(&block) end.
- #lock ⇒ Mutex
- #locked? ⇒ Boolean
-
#sleep(timeout = nil) ⇒ Numeric
Releases the lock and sleeps timeout seconds if it is given and non-nil or forever.
-
#synchronize ⇒ Object
Acquire the lock, yield the block, then ensure the lock is unlocked.
- #try_lock ⇒ Boolean
- #unlock ⇒ Mutex
Constructor Details
Instance Method Details
#lock ⇒ Mutex
37 38 39 40 41 42 43 44 45 |
# File 'lib/process_shared/mutex.rb', line 37 def lock if locked_by == ::Process.pid raise ProcessError, "already locked by this process #{::Process.pid}" end @sem.wait self.locked_by = ::Process.pid self end |
#locked? ⇒ Boolean
48 49 50 |
# File 'lib/process_shared/mutex.rb', line 48 def locked? locked_by > 0 end |
#sleep(timeout = nil) ⇒ Numeric
Releases the lock and sleeps timeout seconds if it is given and non-nil or forever.
56 57 58 59 60 61 62 63 |
# File 'lib/process_shared/mutex.rb', line 56 def sleep(timeout = nil) unlock begin timeout ? Kernel.sleep(timeout) : Kernel.sleep ensure lock end end |
#synchronize ⇒ Object
Acquire the lock, yield the block, then ensure the lock is unlocked.
93 94 95 96 97 98 99 100 |
# File 'lib/process_shared/mutex.rb', line 93 def synchronize lock begin yield ensure unlock end end |
#try_lock ⇒ Boolean
66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/process_shared/mutex.rb', line 66 def try_lock with_internal_lock do if @locked_by.get_int(0) > 0 false # was locked else @sem.wait # should return immediately self.locked_by = ::Process.pid true end end end |
#unlock ⇒ Mutex
79 80 81 82 83 84 85 86 87 |
# File 'lib/process_shared/mutex.rb', line 79 def unlock if (p = locked_by) != ::Process.pid raise ProcessError, "lock is held by #{p} not #{::Process.pid}" end self.locked_by = 0 @sem.post self end |