I’m relatively new to Ruby, having switched from a PHP and Java
background, and I’m having some trouble with the Monitor class trying to
implement a synchronised circular buffer. The other posts here on
synchronised methods aren’t quite relevant enough unfortunately.
My current implementation is the following
require ‘monitor’
class SynchronisedBuffer < Monitor
def initialize(capacity)
@capacity = capacity
@front = 0
@back = 0
@elements = Array.new(capacity)
@empty_cond = new_cond
@full_cond = new_cond
super()
end
def get
@empty_cond.wait_while {empty?}
element = nil
synchronize do
element = @elements[@front]
@elements[@front] = nil
@front = (@front + 1) % @capacity
@full_cond.signal
end
return element
end
def put(element)
@full_cond.wait_while {full?}
synchronize do
@elements[@back] = element
@back = (@back + 1) % @capacity
@empty_cond.signal
end
end
def full?
result = false
synchronize do
result = (@front == @back and @elements[@front] != nil)
end
return result
end
def empty?
result = false
synchronize do
result = (@front == @back and @elements[@front] == nil)
end
return result
end
end
This has been adapted from a version I had written in Java. The problem
is that when I have a thread call ‘get’ on the buffer, I receive a
ThreadException saying ‘current thread not owner’
This is being thrown by mon_check_owner, and a bit of poking around
shows that it fails because mon_owner is set to nil in the condition
‘@mon_owner != Thread.current’.
I am using the buffer for a simple producer/consumer web server, like so
buffer = SynchronisedBuffer.new(10)
workers = []
for i in (1…10)
workers[i] = Worker.new(buffer)
end
while socket = server.accept
buffer.put(socket)
end
I’m writing this purely to gain a better understanding of some important
ruby classes like thread, monitor and socket, and am aware that there
are other ruby web servers I could use straight away :). I’m also trying
to understand the ‘ruby way’ of coding, so any comments as to how the
above code might better be written would be really appreciated.
Sam D.