Class: Tsafe::Mrswlock
- Inherits:
-
Object
- Object
- Tsafe::Mrswlock
- Defined in:
- lib/tsafe_mrswlock.rb,
lib/tsafe_mrswlock_jruby.rb
Overview
A class that allows many simultanious read-synchronizations but locks both reading and writing while calling the write-synchronzie-method. This is the JRuby-version and will not work under anything else. It uses ‘java.util.concurrent.locks.ReentrantReadWriteLock’ instead of doing the locking in Ruby.
Instance Method Summary collapse
-
#initialize ⇒ Mrswlock
constructor
Sets various variables.
-
#rsync ⇒ Object
Runs the given block through the read-synchronization.
-
#wsync ⇒ Object
Runs the given block through the write-synchronization (locks both reading and writing).
Constructor Details
#initialize ⇒ Mrswlock
Sets various variables.
6 7 8 9 10 11 12 13 14 15 16 |
# File 'lib/tsafe_mrswlock.rb', line 6 def initialize @reads = 0 @w_mutex = Mutex.new @threads_read_stopped = [] # This variable is used to allow reads from the writing thread (monitor-behavior). @locked_by = nil # This hash holds thread-IDs for threads that are reading. @reading_threads = {} end |
Instance Method Details
#rsync ⇒ Object
Runs the given block through the read-synchronization.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/tsafe_mrswlock.rb', line 19 def rsync begin tid = Thread.current.__id__ while @w_mutex.locked? && @locked_by != tid @threads_read_stopped << Thread.current Thread.stop end @threads_read_stopped.delete(Thread.current) @reading_threads[tid] = true @reads += 1 yield ensure @reading_threads.delete(tid) @reads -= 1 end ensure # Restart stopped writing-thread. @threads_write_stopped.run if @threads_write_stopped && @reads <= 0 end |
#wsync ⇒ Object
Runs the given block through the write-synchronization (locks both reading and writing).
Examples
lock.wsync do
#do something within lock.
end
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/tsafe_mrswlock.rb', line 46 def wsync @w_mutex.synchronize do begin tid = Thread.current.__id__ @locked_by = tid # Wait for any reads to finish that might have started while we were getting the lock. # Also allow write if there is only one reading thread and that reading thread is the current thread. while @reads > 0 raise ThreadError, "Deadlock: Writing is not allowed while reading." if @reading_threads.key?(tid) @threads_write_stopped = Thread.current Thread.stop end yield ensure @locked_by = nil @threads_write_stopped = nil end end ensure # Restart any stopped reading-threads. while (thread = @threads_read_stopped.shift) thread.run end end |