Class: Tsafe::Mrswlock

Inherits:
Object
  • Object
show all
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

Constructor Details

#initializeMrswlock

Sets various variables.



6
7
8
9
10
11
12
13
14
15
# File 'lib/tsafe_mrswlock.rb', line 6

def initialize
  @reads = 0
  @w_mutex = Mutex.new
  
  #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

#rsyncObject

Runs the given block through the read-synchronization.



18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/tsafe_mrswlock.rb', line 18

def rsync
  begin
    tid = Thread.current.__id__
    Thread.pass while @w_mutex.locked? and @locked_by != tid
    @reading_threads[tid] = true
    @reads += 1
    yield
  ensure
    @reading_threads.delete(tid)
    @reads -= 1
  end
end

#wsyncObject

Runs the given block through the write-synchronization (locks both reading and writing).

Examples

lock.wsync do
  #do something within lock.
end

Raises:

  • (ThreadError)


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/tsafe_mrswlock.rb', line 36

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)
        Thread.pass
      end
      
      yield
    ensure
      @locked_by = nil
    end
  end
end