Skip to content

Instantly share code, notes, and snippets.

@haileys
Created February 22, 2014 13:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haileys/9154796 to your computer and use it in GitHub Desktop.
Save haileys/9154796 to your computer and use it in GitHub Desktop.
require "thread"
Thread.abort_on_exception = true
class ReadWriteLock
def initialize
@lock_request_queue = SizedQueue.new(1)
@thread = Thread.new { thread_main }
@readers = 0
@writer_queue = []
end
def synchronize_read
@lock_request_queue << :lock_read
yield
ensure
@lock_request_queue << :unlock_read
end
def synchronize_write
lock_request = SizedQueue.new(1)
@lock_request_queue << lock_request
unlocker = lock_request.deq
yield
ensure
unlocker << :unlock_write
end
def close
@thread.kill
end
private
def thread_main
loop do
case request = @lock_request_queue.deq
when :lock_read
@readers += 1
when :unlock_read
@readers -= 1
if @readers == 0 && @writer_queue.any?
lock_for_write(@writer_queue.shift)
end
when SizedQueue
if @readers == 0
lock_for_write(request)
else
@writer_queue << request
end
end
end
end
def lock_for_write(queue)
unlock_request_queue = SizedQueue.new(1)
queue << unlock_request_queue
unlock_request_queue.deq
if @writer_queue.any?
lock_for_write(@writer_queue.shift)
end
end
end
q = ReadWriteLock.new
th = nil
q.synchronize_read do
q.synchronize_read do
th = Thread.start do
q.synchronize_write do
puts "writing!"
end
end
sleep 0.01
puts "reading!"
end
sleep 0.01
puts "reading!"
end
th.join
q.close
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment