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
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

#rsyncObject

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

#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)


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