home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / ruby / 1.8 / weakref.rb < prev    next >
Encoding:
Ruby Source  |  2006-08-04  |  2.6 KB  |  95 lines

  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.     @__id = orig.__id__
  52.     ObjectSpace.define_finalizer orig, @@final
  53.     ObjectSpace.define_finalizer self, @@final
  54.     __old_status = Thread.critical
  55.     begin
  56.       Thread.critical = true
  57.       @@id_map[@__id] = [] unless @@id_map[@__id]
  58.     ensure
  59.       Thread.critical = __old_status
  60.     end
  61.     @@id_map[@__id].push self.__id__
  62.     @@id_rev_map[self.__id__] = @__id
  63.   end
  64.  
  65.   # Return the object this WeakRef references. Raises RefError if the object
  66.   # has been garbage collected.  The object returned is the object to which
  67.   # method calls are delegated (see Delegator).
  68.   def __getobj__
  69.     unless @@id_rev_map[self.__id__] == @__id
  70.       raise RefError, "Illegal Reference - probably recycled", caller(2)
  71.     end
  72.     begin
  73.       ObjectSpace._id2ref(@__id)
  74.     rescue RangeError
  75.       raise RefError, "Illegal Reference - probably recycled", caller(2)
  76.     end
  77.   end
  78.  
  79.   # Returns true if the referenced object still exists, and false if it has
  80.   # been garbage collected.
  81.   def weakref_alive?
  82.     @@id_rev_map[self.__id__] == @__id
  83.   end
  84. end
  85.  
  86. if __FILE__ == $0
  87.   require 'thread'
  88.   foo = Object.new
  89.   p foo.to_s            # original's class
  90.   foo = WeakRef.new(foo)
  91.   p foo.to_s            # should be same class
  92.   ObjectSpace.garbage_collect
  93.   p foo.to_s            # should raise exception (recycled)
  94. end
  95.