diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/delegate.rb | 76 | ||||
-rw-r--r-- | lib/weakref.rb | 11 |
2 files changed, 39 insertions, 48 deletions
diff --git a/lib/delegate.rb b/lib/delegate.rb index 1d0ebed07a..83aaf292a5 100644 --- a/lib/delegate.rb +++ b/lib/delegate.rb @@ -17,44 +17,27 @@ # end class Delegator + preserved = ["__id__", "object_id", "__send__", "respond_to?"] + instance_methods.each do |m| + next if preserved.include?(m) + undef_method m + end def initialize(obj) - preserved = ::Kernel.public_instance_methods(false) - preserved -= ["to_s","to_a","inspect","==","=~","==="] - for t in self.class.ancestors - preserved |= t.public_instance_methods(false) - preserved |= t.private_instance_methods(false) - preserved |= t.protected_instance_methods(false) - break if t == Delegator - end - preserved << "singleton_method_added" - for method in obj.methods - next if preserved.include? method - begin - eval <<-EOS - def self.#{method}(*args, &block) - begin - __getobj__.__send__(:#{method}, *args, &block) - rescue Exception - $@.delete_if{|s| /:in `__getobj__'$/ =~ s} #` - $@.delete_if{|s| /^\\(eval\\):/ =~ s} - ::Kernel::raise - end - end - EOS - rescue SyntaxError - raise NameError, "invalid identifier %s" % method, caller(4) - end - end + __setobj__(obj) end - alias initialize_methods initialize def method_missing(m, *args) - target = self.__getobj__ - unless target.respond_to?(m) - super(m, *args) + begin + target = self.__getobj__ + unless target.respond_to?(m) + super(m, *args) + end + target.__send__(m, *args) + rescue Exception + $@.delete_if{|s| /^#{__FILE__}:\d+:in `method_missing'$/ =~ s} #` + ::Kernel::raise end - target.__send__(m, *args) end def respond_to?(m) @@ -66,21 +49,19 @@ class Delegator raise NotImplementedError, "need to define `__getobj__'" end + def __setobj__(obj) + raise NotImplementedError, "need to define `__setobj__'" + end + def marshal_dump __getobj__ end def marshal_load(obj) - initialize_methods(obj) + __setobj__(obj) end end class SimpleDelegator<Delegator - - def initialize(obj) - super - @_sd_obj = obj - end - def __getobj__ @_sd_obj end @@ -91,12 +72,14 @@ class SimpleDelegator<Delegator end def clone - super - __setobj__(__getobj__.clone) + copy = super + copy.__setobj__(__getobj__.clone) + copy end def dup - super - __setobj__(__getobj__.dup) + copy = super + copy.__setobj__(__getobj__.dup) + copy end end @@ -108,8 +91,11 @@ SimpleDelegater = SimpleDelegator def DelegateClass(superclass) klass = Class.new methods = superclass.public_instance_methods(true) - methods -= ::Kernel.public_instance_methods(false) - methods |= ["to_s","to_a","inspect","==","=~","==="] + methods -= [ + "__id__", "object_id", "__send__", "respond_to?", + "initialize", "method_missing", "__getobj__", "__setobj__", + "clone", "dup", "marshal_dump", "marshal_load", + ] klass.module_eval { def initialize(obj) @_dc_obj = obj diff --git a/lib/weakref.rb b/lib/weakref.rb index c790055d01..a398ebf1fe 100644 --- a/lib/weakref.rb +++ b/lib/weakref.rb @@ -18,7 +18,8 @@ class WeakRef<Delegator @@id_map = {} # obj -> [ref,...] @@id_rev_map = {} # ref -> obj - @@final = lambda{|id| + @@final = lambda {|id| + printf "final: %p\n", id __old_status = Thread.critical Thread.critical = true begin @@ -42,6 +43,7 @@ class WeakRef<Delegator def initialize(orig) @__id = orig.object_id + printf "orig: %p\n", @__id ObjectSpace.define_finalizer orig, @@final ObjectSpace.define_finalizer self, @@final __old_status = Thread.critical @@ -53,7 +55,7 @@ class WeakRef<Delegator end @@id_map[@__id].push self.object_id @@id_rev_map[self.object_id] = @__id - super + super end def __getobj__ @@ -66,6 +68,8 @@ class WeakRef<Delegator Kernel::raise RefError, "Illegal Reference - probably recycled", Kernel::caller(2) end end + def __setobj__(obj) + end def weakref_alive? @@id_rev_map[self.object_id] == @__id @@ -73,11 +77,12 @@ class WeakRef<Delegator end if __FILE__ == $0 - require 'thread' +# require 'thread' foo = Object.new p foo.to_s # original's class foo = WeakRef.new(foo) p foo.to_s # should be same class ObjectSpace.garbage_collect + ObjectSpace.garbage_collect p foo.to_s # should raise exception (recycled) end |