#
# recycle.rb
#
#     Copyright (c) 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
#
#
# usage:
#
# class A
#   include Recyclable
#   :
# end
#
# a = A.new( arg, to, class_a )
# puts a.id                                 #--> 5489
# A.finished a
#    :
# A.use_instance( arg, to, class_a ) do |a|
#   puts a.id                               #--> 5489
# end
#
# puts A.new.id                             #--> 5489
#


module Recyclable

  BEGIN_GC_SIZE = 5


  def Recyclable.append_features( mod )
    super

    mod.module_eval '@spare = []'

    def mod.new( *args, &block )
      gavage_collect

      if @spare.size > 0 then
        inst = @spare.pop  # recycle
        inst.reset( *args, &block )
      else
        inst = super         # make new
      end

      return inst
    end

    def mod.use_instance( *args, &block )
      inst = new( *args, &block )
      block.call inst
      inst.type.finished inst
    end

    def mod.finished( inst )
      @spare.push inst
      gavage_collect
    end

    def mod.gavage_collect
      if @spare.size > Recyclable::BEGIN_GC_SIZE then
        @spare = @spare[ 0, @spare.size / 2 ]
      end
    end
  
  end

end
