# Synchronized Circular Buffer

**URL:** <https://www.ruby-forum.com/t/synchronized-circular-buffer/226069>\
**Category:** Ruby\
**Created:** [July 1, 2010, 10:31am UTC](https://www.ruby-forum.com/t/synchronized-circular-buffer/226069 "2010-07-01T10:31:39Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![samonderous](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/3da27b/32.png) [@samonderous](https://www.ruby-forum.com/u/samonderous)\
**Post date:** [July 1, 2010, 10:31am UTC](https://www.ruby-forum.com/t/synchronized-circular-buffer/226069/1 "2010-07-01T10:31:39Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![samonderous](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/3da27b/32.png) [@samonderous](https://www.ruby-forum.com/u/samonderous)\
**Post date:** [July 1, 2010, 12:10pm UTC](https://www.ruby-forum.com/t/synchronized-circular-buffer/226069/2 "2010-07-01T12:10:34Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![samonderous](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/3da27b/32.png) [@samonderous](https://www.ruby-forum.com/u/samonderous)\
**Post date:** [July 1, 2010, 11:12am UTC](https://www.ruby-forum.com/t/synchronized-circular-buffer/226069/3 "2010-07-01T11:12:38Z")

</div>

2010/7/1 Sam D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

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

> ```
> 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. 🙂

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

> workers[i] = Worker.new(buffer)  
> 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

---

<div class="post-metadata">

**Author:** ![samonderous](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/3da27b/32.png) [@samonderous](https://www.ruby-forum.com/u/samonderous)\
**Post date:** [July 1, 2010, 1:14pm UTC](https://www.ruby-forum.com/t/synchronized-circular-buffer/226069/4 "2010-07-01T13:14:59Z")

</div>

2010/7/1 Sam D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> 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] [Mailing Lists](http://www.ruby-lang.org/en/community/mailing-lists/)
