daily pastebin goal
28%
SHARE
TWEET

Untitled

a guest Jun 18th, 2018 68 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. require "delegate"
  2.  
  3. # WeakRef is a class to represent a reference to an object that is not seen by
  4. # the tracing phase of the garbage collector.  This allows the referenced
  5. # object to be garbage collected as if nothing is referring to it. Because
  6. # WeakRef delegates method calls to the referenced object, it may be used in
  7. # place of that object, i.e. it is of the same duck type.
  8. #
  9. # Usage:
  10. #
  11. #   foo = Object.new
  12. #   foo = Object.new
  13. #   p foo.to_s                  # original's class
  14. #   foo = WeakRef.new(foo)
  15. #   p foo.to_s                  # should be same class
  16. #   ObjectSpace.garbage_collect
  17. #   p foo.to_s                  # should raise exception (recycled)
  18. class WeakRef<Delegator
  19.  
  20.   # RefError is raised if an object cannot be referenced by a WeakRef.
  21.   class RefError<StandardError
  22.   end
  23.  
  24.   @@id_map =  {}                # obj -> [ref,...]
  25.   @@id_rev_map =  {}            # ref -> obj
  26.   @@final = lambda{|id|
  27.     __old_status = Thread.critical
  28.     Thread.critical = true
  29.     begin
  30.       rids = @@id_map[id]
  31.       if rids
  32.         for rid in rids
  33.           @@id_rev_map.delete(rid)
  34.         end
  35.         @@id_map.delete(id)
  36.       end
  37.       rid = @@id_rev_map[id]
  38.       if rid
  39.         @@id_rev_map.delete(id)
  40.         @@id_map[rid].delete(id)
  41.         @@id_map.delete(rid) if @@id_map[rid].empty?
  42.       end
  43.     ensure
  44.       Thread.critical = __old_status
  45.     end
  46.   }
  47.  
  48.   # Create a new WeakRef from +orig+.
  49.   def initialize(orig)
  50.     super
  51.     __setobj__(orig)
  52.   end
  53.  
  54.   # Return the object this WeakRef references. Raises RefError if the object
  55.   # has been garbage collected.  The object returned is the object to which
  56.   # method calls are delegated (see Delegator).
  57.   def __getobj__
  58.     unless @@id_rev_map[self.__id__] == @__id
  59.       raise RefError, "Illegal Reference - probably recycled", caller(2)
  60.     end
  61.     begin
  62.       ObjectSpace._id2ref(@__id)
  63.     rescue RangeError
  64.       raise RefError, "Illegal Reference - probably recycled", caller(2)
  65.     end
  66.   end
  67.  
  68.   def __setobj__(obj)
  69.     @__id = obj.__id__
  70.     __old_status = Thread.critical
  71.     begin
  72.       Thread.critical = true
  73.       unless @@id_rev_map.key?(self)
  74.         ObjectSpace.define_finalizer obj, @@final
  75.         ObjectSpace.define_finalizer self, @@final
  76.       end
  77.       @@id_map[@__id] = [] unless @@id_map[@__id]
  78.     ensure
  79.       Thread.critical = __old_status
  80.     end
  81.     @@id_map[@__id].push self.__id__
  82.     @@id_rev_map[self.__id__] = @__id
  83.   end
  84.  
  85.   # Returns true if the referenced object still exists, and false if it has
  86.   # been garbage collected.
  87.   def weakref_alive?
  88.     @@id_rev_map[self.__id__] == @__id
  89.   end
  90. end
  91.  
  92. if __FILE__ == $0
  93.   require 'thread'
  94.   foo = Object.new
  95.   p foo.to_s                    # original's class
  96.   foo = WeakRef.new(foo)
  97.   p foo.to_s                    # should be same class
  98.   ObjectSpace.garbage_collect
  99.   p foo.to_s                    # should raise exception (recycled)
  100. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top