diff options
Diffstat (limited to 'lib/weakref.rb')
| -rw-r--r-- | lib/weakref.rb | 95 |
1 files changed, 42 insertions, 53 deletions
diff --git a/lib/weakref.rb b/lib/weakref.rb index d53aa15c71..c7274f9664 100644 --- a/lib/weakref.rb +++ b/lib/weakref.rb @@ -1,70 +1,59 @@ -# Weak Reference class that does not bother GCing. +# frozen_string_literal: true +require "delegate" + +# Weak Reference class that allows a referenced object to be +# garbage-collected. +# +# A WeakRef may be used exactly like the object it references. # # Usage: -# foo = Object.new -# foo.hash -# foo = WeakRef.new(foo) -# foo.hash -# ObjectSpace.garbage_collect -# foo.hash # => Raises WeakRef::RefError (because original GC'ed) +# +# foo = Object.new # create a new object instance +# p foo.to_s # original's class +# foo = WeakRef.new(foo) # reassign foo with WeakRef instance +# p foo.to_s # should be same class +# GC.start # start the garbage collector +# p foo.to_s # should raise exception (recycled) +# -require "delegate" +class WeakRef < Delegator + # The version string + VERSION = "0.1.4" -class WeakRef<Delegator + ## + # RefError is raised when a referenced object has been recycled by the + # garbage collector - class RefError<StandardError + class RefError < StandardError end - ID_MAP = {} - ID_REV_MAP = {} - ObjectSpace.add_finalizer(lambda{|id| - rid = ID_MAP[id] - if rid - ID_REV_MAP[rid] = nil - ID_MAP[id] = nil - end - rid = ID_REV_MAP[id] - if rid - ID_REV_MAP[id] = nil - ID_MAP[rid] = nil - end - }) - + @@__map = ::ObjectSpace::WeakMap.new + + ## + # Creates a weak reference to +orig+ + def initialize(orig) + case orig + when true, false, nil + @delegate_sd_obj = orig + else + @@__map[self] = orig + end super - @__id = orig.__id__ - ObjectSpace.call_finalizer orig - ObjectSpace.call_finalizer self - ID_MAP[@__id] = self.__id__ - ID_REV_MAP[self.id] = @__id end - def __getobj__ - unless ID_MAP[@__id] - raise RefError, "Illegal Reference - probably recycled", caller(2) - end - ObjectSpace._id2ref(@__id) + def __getobj__(&_block) # :nodoc: + @@__map[self] or defined?(@delegate_sd_obj) ? @delegate_sd_obj : + Kernel::raise(RefError, "Invalid Reference - probably recycled", Kernel::caller(2)) end - def weakref_alive? - if ID_MAP[@__id] - true - else - false - end + def __setobj__(obj) # :nodoc: end - def [] - __getobj__ - end -end + ## + # Returns true if the referenced object is still alive. -if __FILE__ == $0 - 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 - p foo.to_s # should raise exception (recycled) + def weakref_alive? + @@__map.key?(self) or defined?(@delegate_sd_obj) + end end |
