# ObjectPool -- Sharing of instantiated objects. # # Copyright (C) 2001 Masao Mutoh # This program is licenced under the same licence as Ruby. # # $Id: objectpool.rb,v 1.1.1.1 2001/12/30 13:12:19 mutoh Exp $ # require 'singleton' require 'timeout' require 'thread' class ObjectPool include Singleton alias _timeout timeout def initialize @used_list = {} @free_list = [] @max = 10 @timeout = nil @mutex = Mutex.new @cond = ConditionVariable.new end def get @mutex.synchronize { if !@free_list.empty? result = @free_list.pop elsif @used_list.size < @max result = create else begin _timeout(@timeout){ @cond.wait(@mutex) } rescue TimeoutError raise TimeoutError.new("There are no more available Objects. max = %d" % @max) end result = @free_list.pop end @used_list.store(result.__id__, result) result } end # Release an object. # This method does not mean that the object is actually released. # If you do, you can use the obect after release, but you should avoid # as much as possible. def release(obj) @mutex.synchronize { @used_list.delete(obj.__id__) @free_list.push(obj) @cond.signal } nil end def max=(size) @mutex.synchronize { if @free_list.size + @used_list.size > size raise ArgumentError.new("Cannot change max size to %d. There are objects over the size." % size) end @max = size } size end def create raise "Implement this method." end attr_reader :max attr_accessor :timeout end if __FILE__ == $0 class Test end class TestPool < ObjectPool def initialize super self.max = 3 self.timeout = 10 end def create Test.new end end objectpool = TestPool.instance p a = objectpool.get p b = objectpool.get # a, b, c are not same object. p c = objectpool.get # a, b, c are not same object. objectpool.release(a) # release a. p "released = %s" % a p d = objectpool.get # d and a is same object. Thread.new do sleep 5 objectpool.release(b) # after 5 sec, release b. end p e = objectpool.get # wait 5 sec until b is released. # e and b is same object. end