Prev: [ANN] Ruby Hoedown 2010 Registration Open and CFP Closing Soon!
Next: Fast searching of large files
From: Sam Dalton on 1 Jul 2010 04:31 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 Dalton -- Posted via http://www.ruby-forum.com/.
From: Robert Klemme on 1 Jul 2010 05:10 2010/7/1 Sam Dalton <mail(a)samdalton.co.nz>: > 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?} The line above must be moved into the synchronized block. > element = nil No need for this. > synchronize do > element = @elements[@front] > @elements[@front] = nil > @front = (@front + 1) % @capacity > @full_cond.signal > end Just move the next line into the block. > return element > end > > def put(element) > @full_cond.wait_while {full?} The line above must be moved down 1 line. > 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 This is sufficient: def full? synchronize do (@front == @back and @elements[@front] != nil) end end > end > > def empty? Same as above - saves you some typing. :-) > 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' You need to be holding the lock when waiting on a condition variable (same story in Java btw). > 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. That's usually a good thing to do. I do it myself all the time. Nothing beats one's own experience. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/
From: Sam Dalton on 1 Jul 2010 06:10 Hi Robert, Thanks for the help, it works perfectly now. I see that I should treat the synchronised block as wrapping the entire method body, just as the synchronise keyword would in Java. Makes sense :) Is it possible to subscribe to this forum via RSS (or another method)? Looking forward to the day when I've improved enough to help others. Regards, Sam -- Posted via http://www.ruby-forum.com/.
From: Robert Klemme on 1 Jul 2010 07:14 2010/7/1 Sam Dalton <mail(a)samdalton.co.nz>: > Thanks for the help, it works perfectly now. I see that I should treat > the synchronised block as wrapping the entire method body, just as the > synchronise keyword would in Java. Makes sense :) Not necessarily. The synchronized block must be only as long as necessary to guard the critical section. I'd rather say, it's bad to always synchronize complete methods. > Is it possible to subscribe to this forum via RSS (or another method)? There is news:comp.lang.ruby and ruby-talk mailing list - all are mirrored full duplex (see [1]). > Looking forward to the day when I've improved enough to help others. The day will come - inevitably. :-) Kind regards robert [1] http://www.ruby-lang.org/en/community/mailing-lists/ -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/
|
Pages: 1 Prev: [ANN] Ruby Hoedown 2010 Registration Open and CFP Closing Soon! Next: Fast searching of large files |