[#10492] Ruby 1.8.6 preview3 has been released — "Akinori MUSHA" <knu@...>

Hi,

26 messages 2007/03/04
[#10500] Re: Ruby 1.8.6 preview3 has been released — Hugh Sasse <hgs@...> 2007/03/05

On Mon, 5 Mar 2007, Akinori MUSHA wrote:

[#10507] Dynamic Array#join with block — <noreply@...>

Patches item #9055, was opened at 2007-03-05 19:57

12 messages 2007/03/05
[#10520] Re: [ ruby-Patches-9055 ] Dynamic Array#join with block — Nobuyoshi Nakada <nobu@...> 2007/03/06

Hi,

[#10594] grave bug in 1.8.6's thread implementation — Sylvain Joyeux <sylvain.joyeux@...4x.org>

In ext/thread/thread.c, remove_one leaves the list in an inconsistent state.

15 messages 2007/03/14
[#10596] Re: [PATCH] grave bug in 1.8.6's thread implementation — MenTaLguY <mental@...> 2007/03/14

On Thu, 15 Mar 2007 00:15:57 +0900, Sylvain Joyeux <sylvain.joyeux@m4x.org> wrote:

[#10597] Re: [PATCH] grave bug in 1.8.6's thread implementation — Sylvain Joyeux <sylvain.joyeux@...4x.org> 2007/03/14

> > The fix is in thread-mutex-remove_one.diff.

[#10598] Re: [PATCH] grave bug in 1.8.6's thread implementation — MenTaLguY <mental@...> 2007/03/14

On Thu, 15 Mar 2007 01:19:04 +0900, Sylvain Joyeux <sylvain.joyeux@m4x.org> wrote:

[#10599] Re: [PATCH] grave bug in 1.8.6's thread implementation — Sylvain Joyeux <sylvain.joyeux@...4x.org> 2007/03/14

On Wednesday 14 March 2007 17:29, MenTaLguY wrote:

[#10600] Re: [PATCH] grave bug in 1.8.6's thread implementation — MenTaLguY <mental@...> 2007/03/14

On Thu, 15 Mar 2007 01:48:42 +0900, Sylvain Joyeux <sylvain.joyeux@m4x.org> wrote:

[#10615] Multiton in standard library — TRANS <transfire@...>

Hi--

16 messages 2007/03/15
[#10619] Re: Multiton in standard library — Tom Pollard <tomp@...> 2007/03/16

[#10620] Re: Multiton in standard library — TRANS <transfire@...> 2007/03/16

On 3/15/07, Tom Pollard <tomp@earthlink.net> wrote:

[#10646] Marshal.dump shouldn't complain about singletons if the _dump method is defined — <noreply@...>

Bugs item #9376, was opened at 2007-03-19 15:58

12 messages 2007/03/19
[#10647] Re: [ ruby-Bugs-9376 ] Marshal.dump shouldn't complain about singletons if the _dump method is defined — Urabe Shyouhei <shyouhei@...> 2007/03/19

noreply@rubyforge.org wrote:

[#10648] Re: [ ruby-Bugs-9376 ] Marshal.dump shouldn't complain about singletons if the _dump method is defined — Sylvain Joyeux <sylvain.joyeux@...4x.org> 2007/03/19

On Monday 19 March 2007 18:01, Urabe Shyouhei wrote:

[#10651] Re: [ ruby-Bugs-9376 ] Marshal.dump shouldn't complain about singletons if the _dump method is defined — Yukihiro Matsumoto <matz@...> 2007/03/19

Hi,

[#10665] Re: [ ruby-Bugs-9376 ] Marshal.dump shouldn't complain about singletons if the _dump method is defined — "Chris Carter" <cdcarter@...> 2007/03/20

On 3/19/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

[#10712] Ruby Method Signatures (was Re: Multiton in standard library) — "Rick DeNatale" <rick.denatale@...>

On 3/19/07, TRANS <transfire@gmail.com> wrote:

10 messages 2007/03/21
[#10715] Re: Ruby Method Signatures (was Re: Multiton in standard library) — Jos Backus <jos@...> 2007/03/22

On 3/19/07, TRANS <transfire@gmail.com> wrote:

[#10798] Virtual classes and 'real' classes -- why? — "John Lam (CLR)" <jflam@...>

I was wondering if someone could help me understand why there's a parallel =

12 messages 2007/03/28
[#10799] Re: Virtual classes and 'real' classes -- why? — MenTaLguY <mental@...> 2007/03/28

On Thu, 29 Mar 2007 04:44:16 +0900, "John Lam (CLR)" <jflam@microsoft.com> wrote:

Multiton in standard library

From: TRANS <transfire@...>
Date: 2007-03-15 22:08:13 UTC
List: ruby-core #10615
Hi--

I would like to propose that the Multiton pattern be supported in
Ruby's standard library. I believe the Multiton module originally
developed by Ara T. Howard and improved by myself is pretty solid at
this point. So I would like to offer it for the purpose.

The code follows for others to consider. And please let me know if you
have any suggestions for improving it further.

Thanks,
Trans

---

# = Multiton
#
# Multiton module that ensures only one object to be allocated for a given
# argument list.
#
# The 'multiton' pattern is similar to a singleton, but instead of only one
# instance, there are several similar instances.  It is useful when you want to
# avoid constructing objects many times because of some huge expense (connecting
# to a database for example), require a set of similar but not identical
# objects, and cannot easily control how many times a contructor may be called.
#
# == Synopsis
#
#   class SomeMultitonClass
#     include Multiton
#     attr :arg
#     def initialize(arg)
#       @arg = arg
#     end
#   end
#
#   a = SomeMultitonClass.new(4)
#   b = SomeMultitonClass.new(4)   # a and b are same object
#   c = SomeMultitonClass.new(2)   # c is a different object
#
# == Previous Behavior
#
# In previous versions of Multiton the #new method was made
# private and #instance was used in its stay --just like Singleton.
# But this has proved less desirable for Multiton since Multitions can
# have multiple instances, not just one.
#
# So instead Multiton now defines #create as a private alias of
# the original #new method (just in case it is needed) and then
# defines #new to handle the multiton, and #instance is provided
# as an alias for it.
#
# == How It Works
#
# A pool of objects is searched for a previously cached object,
# if one is not found we construct one and cache it in the pool
# based on class and the args given to the contructor. To ensure
# equvalence, arguments are round-tripeed through Marshal. So
# only objects that can be marshalled can serve as arguments for
# the cache.
#
# Another limitation is that it is impossible to detect if different
# blocks were given to a contructor (if it takes a  block).  So it
# is the constructor arguments _only_ which determine the uniqueness
# of an object. To workaround this, define the _class_ method
# ::multiton_id.
#
#   def Klass.multiton_id(*args, &block)
#     # ...
#   end
#
# Which should return a hash key used to identify the object being
# constructed as (not) unique.

module Multiton

  # Pools of objects cached on class type.
  POOLS = {}

  # Method which can be defined by a class to determine object uniqueness.
  MULTITON_ID_HOOK = :multiton_id

  # Method which can be defined by a class to create multiton objects.
  MULTITON_NEW_HOOK = :multiton_new

  def self.append_features( klass )

    class << klass

      unless method_defined?(MULTITON_NEW_HOOK)
        alias_method MULTITON_NEW_HOOK, :new
      end

      # Define #instance method. This will become #new.

      def instance(*args, &block)
        # if the class defined 'multiton_id' we use this as the key
        # otherwise we simply use the argument list
        k = begin
          send MULTITON_ID_HOOK, *args, &block
        rescue NameError
          args
        end
        # marshal the args to serve as cache key (b/c hashes fail as this)
        k = begin
          Marshal.dump(k)
        rescue TypeError
          k
        end
        # Return cached object. Set if first occurance.
        unless obj = (POOLS[self] ||= {})[k]
          begin
            critical = Thread.critical
            Thread.critical = true
            obj = (POOLS[self][k] = send(MULTITON_NEW_HOOK, *args, &block))
          ensure
            Thread.critical = critical # restore state
          end
        end

        return obj
      end

      alias_method :create, :new
      alias_method :new, :instance
    end
  end

  ## DON'T NEED THANKS TO MARSHAL
  # Recursive dehash function. This converts hash into associative
  # arrays, and any hashes that contains, etc.
  #def self.dehash(arg)
  #  case arg
  #  when Hash
  #    arg.to_a.collect{|a| dehash(a)}
  #  when Array
  #    arg.collect{|a| dehash(a)}
  #  else
  #    arg
  #  end
  #end

end



#  _____         _
# |_   _|__  ___| |_
#   | |/ _ \/ __| __|
#   | |  __/\__ \ |_
#   |_|\___||___/\__|
#

=begin test

  require 'test/unit'

  #
  # EXAMPLE A - STANDARD USAGE
  #
  class TC_Multiton_A < Test::Unit::TestCase

    class SomeMultitonClass
      include Multiton
      attr :arg
      def initialize(arg)
        @arg = arg
      end
    end

    def test_standard

      a = SomeMultitonClass.instance(4)
      b = SomeMultitonClass.instance(4)     # a and b are same object
      c = SomeMultitonClass.instance(2)     # c is a different object

      assert_equal( a, b )
      assert_equal( 42, [a.arg,b.arg].max * 10 + c.arg )

    end

  end

  #
  # EXAMPLE B - MODIFY AN EXISTING CLASS, SHARED FILEHANDLES
  #
  class TC_Multiton_B < Test::Unit::TestCase

    class ::File
      include Multiton
    end

    def test_modify_existing

      lineno = __LINE__
      # HERE1
      # HERE2

      a = File.instance(__FILE__)
      b = File.instance(__FILE__)

      assert_equal( a, b )

      lineno.times{ a.gets }

      assert_equal( "# HERE1", a.gets.strip )
      assert_equal( "# HERE2", b.gets.strip )

    end

  end

  #
  # EXAMPLE C - INHERITENCE
  #
  class TC_Multiton_C < Test::Unit::TestCase

    class A < String
      include Multiton
    end

    # B is also a multiton - with it's OWN object cache
    class B < A; end

    def test_inheritence

      # w is the same object as x, y is the same object as z
      w,x,y,z = A.instance('A'), A.instance('A'), B.instance('B'),
B.instance('B')

      assert_equal( w.object_id, x.object_id ) # -> true
      assert_equal( y.object_id, z.object_id ) # -> true

      a = B.instance('A')
      b = B.instance('A')

      assert_not_equal( a.object_id, w.object_id ) # -> false (each
class has it's own pool)
      assert_equal( a.object_id, b.object_id )     # -> true

    end

  end


  #
  # EXAMPLE D - MULTIPLE MODULE INCLUSION (does nothing)
  #
  class TC_Multiton_D < Test::Unit::TestCase

    class A < String
      include Multiton
    end

    # B is also a multiton - with it's OWN object cache
    class B < A; end

    def test_multiple

      # w is the same object as x, y is the same object as z
      w,x,y,z = A.instance('A'), A.instance('A'), B.instance('B'),
B.instance('B')

      yz_id = y.object_id || z.object_id

      B.class_eval {
        include Multiton
      }

      # y is not only the same object as z, but they are both the same object(s)
      # as from EXAMPLE C

      y,z = B.instance('B'), B.instance('B')

      assert_equal( y.object_id, yz_id )   # -> true
      assert_equal( z.object_id, yz_id ) # -> true

    end

  end

  #
  # EXAMPLE E - SO YOU WANNA USE NEW INSTEAD OF INSTANCE...
  #
  class TC_Multiton_E < Test::Unit::TestCase

    module K
      # use an inner class which is itself a multiton
      class K < String; include Multiton; end

      # define a new which returns a mutltion using #instance...
      class << self
        def new(*args, &block)
          K.instance *args, &block
        end
      end
    end

    def test_new

      the = K.new '4'
      answer = K.new '2'

      assert_equal( "42", sprintf( "%s%s", the, answer ) )  #-> 42
      assert_equal( K::K, the.class )  #-> K::K

    end

  end

  #
  # EXAMPLE F - using Klass.multiton_id
  #
  class TC_Multiton_F < Test::Unit::TestCase

    class Klass
      include Multiton

      def initialize( important, not_important )
        @important, @not_important = important, not_important
      end

      def Klass.multiton_id(*args, &block)
        # we consider only the first arg
        important, not_important = *args
        important
      end
    end

    def test_using_id
      a = Klass.instance( :a, :b )
      b = Klass.instance( :a, :c )
      c = Klass.instance( :b, :b )

      assert_equal( a, b )
      assert_not_equal( a, c )
      assert_not_equal( b, c )
    end

  end

=end

# Author::    Ara T. Howard, Thomas Sawyer
# Copyright:: Copyright (c) 2005-2007 Ara T. Howard, Thomas Sawyer
# License::   Ruby License

In This Thread

Prev Next