[#33640] [Ruby 1.9-Bug#4136][Open] Enumerable#reject should not inherit the receiver's instance variables — Hiro Asari <redmine@...>

Bug #4136: Enumerable#reject should not inherit the receiver's instance variables

10 messages 2010/12/08

[#33667] [Ruby 1.9-Bug#4149][Open] Documentation submission: syslog standard library — mathew murphy <redmine@...>

Bug #4149: Documentation submission: syslog standard library

11 messages 2010/12/10

[#33683] [feature:trunk] Enumerable#categorize — Tanaka Akira <akr@...>

Hi.

14 messages 2010/12/12
[#33684] Re: [feature:trunk] Enumerable#categorize — "Martin J. Dst" <duerst@...> 2010/12/12

[#33687] Towards a standardized AST for Ruby code — Magnus Holm <judofyr@...>

Hey folks,

23 messages 2010/12/12
[#33688] Re: Towards a standardized AST for Ruby code — Charles Oliver Nutter <headius@...> 2010/12/12

On Sun, Dec 12, 2010 at 9:55 AM, Magnus Holm <judofyr@gmail.com> wrote:

[#33689] Re: Towards a standardized AST for Ruby code — "Haase, Konstantin" <Konstantin.Haase@...> 2010/12/12

On Dec 12, 2010, at 17:46 , Charles Oliver Nutter wrote:

[#33763] [Ruby 1.9-Bug#4168][Open] WeakRef is unsafe to use in Ruby 1.9 — Brian Durand <redmine@...>

Bug #4168: WeakRef is unsafe to use in Ruby 1.9

43 messages 2010/12/17

[#33815] trunk warnflags build issue with curb 0.7.9? — Jon <jon.forums@...>

As this may turn out to be a 3rd party issue rather than a bug, I'd like some feedback.

11 messages 2010/12/22

[#33833] Ruby 1.9.2 is going to be released — "Yuki Sonoda (Yugui)" <yugui@...>

-----BEGIN PGP SIGNED MESSAGE-----

15 messages 2010/12/23

[#33846] [Ruby 1.9-Feature#4197][Open] Improvement of the benchmark library — Benoit Daloze <redmine@...>

Feature #4197: Improvement of the benchmark library

15 messages 2010/12/23

[#33910] [Ruby 1.9-Feature#4211][Open] Converting the Ruby and C API documentation to YARD syntax — Loren Segal <redmine@...>

Feature #4211: Converting the Ruby and C API documentation to YARD syntax

10 messages 2010/12/26

[#33923] [Ruby 1.9-Bug#4214][Open] Fiddle::WINDOWS == false on Windows — Jon Forums <redmine@...>

Bug #4214: Fiddle::WINDOWS == false on Windows

15 messages 2010/12/27

[ruby-core:33764] [Ruby 1.9-Bug#4168] WeakRef is unsafe to use in Ruby 1.9

From: Brian Durand <redmine@...>
Date: 2010-12-17 17:43:55 UTC
List: ruby-core #33764
Issue #4168 has been updated by Brian Durand.

File weakref.rb added

Rdoc comments on the WeakReference class didn't get synced with the code. Updated file attached that just fixes the comments.
----------------------------------------
http://redmine.ruby-lang.org/issues/show/4168

----------------------------------------
http://redmine.ruby-lang.org

Attachments (1)

weakref.rb (5.12 KB, text/x-ruby-script)
require 'monitor'

# WeakReference is a class to represent a reference to an object that is not seen by
# the tracing phase of the garbage collector.  This allows the referenced
# object to be garbage collected as if nothing is referring to it.
#
# The difference between this class and WeakRef is that this class does not
# use the delegator pattern and so has an interface more suited for detecting
# if the referenced object has been reclaimed.
#
# Usage:
#
#   foo = Object.new
#   ref = WeakReference.new(foo)
#   ref.object			# should be foo
#   ObjectSpace.garbage_collect
#   ref.object			# should be nil
class WeakReference
  attr_reader :referenced_object_id
  
  # Map of references to the object_id's they refer to.
  @@referenced_object_ids = {}

  # Map of object_ids to references to them.
  @@object_id_references = {}

  @@monitor = Monitor.new

  # Finalizer that cleans up weak references when an object is destroyed.
  @@object_finalizer = lambda do |object_id|
    @@monitor.synchronize do
      reference_ids = @@object_id_references[object_id]
      if reference_ids
    	  reference_ids.each do |reference_object_id|
    	    @@referenced_object_ids.delete(reference_object_id)
    	  end
    	  @@object_id_references.delete(object_id)
  	  end
    end
  end

  # Finalizer that cleans up weak references when references are destroyed.
  @@reference_finalizer = lambda do |object_id|
    @@monitor.synchronize do
      referenced_id = @@referenced_object_ids.delete(object_id)
      if referenced_id
        obj = ObjectSpace._id2ref(referenced_object_id) rescue nil
        if obj
          backreferences = obj.instance_variable_get(:@__weak_backreferences__) if obj.instance_variable_defined?(:@__weak_backreferences__)
          if backreferences
            backreferences.delete(object_id)
            obj.remove_instance_variable(:@__weak_backreferences__) if backreferences.empty?
          end
        end
        references = @@object_id_references[referenced_id]
        if references
          references.delete(object_id)
      	  @@object_id_references.delete(referenced_id) if references.empty?
    	  end
  	  end
    end
  end

  # Create a new weak reference to an object. The existence of the weak reference
  # will not prevent the garbage collector from reclaiming the referenced object.
  def initialize(obj)
    @referenced_object_id = obj.__id__
    ObjectSpace.define_finalizer(obj, @@object_finalizer)
    ObjectSpace.define_finalizer(self, @@reference_finalizer)
    @@monitor.synchronize do
      @@referenced_object_ids[self.__id__] = obj.__id__
      add_backreference(obj)
      references = @@object_id_references[obj.__id__]
      unless references
        references = []
        @@object_id_references[obj.__id__] = references
      end
      references.push(self.__id__)
    end
  end

  # Get the reference object. If the object has already been garbage collected,
  # then this method will return nil.
  def object
    obj = nil
    begin
      if referenced_object_id == @@referenced_object_ids[self.object_id]
        obj = ObjectSpace._id2ref(referenced_object_id)
        obj = nil unless verify_backreferences(obj)
      end
    rescue RangeError
      # Object has been garbage collected.
    end
    obj
  end

  private

    def add_backreference(obj)
      backreferences = obj.instance_variable_get(:@__weak_backreferences__) if obj.instance_variable_defined?(:@__weak_backreferences__)
      unless backreferences
        backreferences = []
        obj.instance_variable_set(:@__weak_backreferences__, backreferences)
      end
      backreferences << object_id
    end

    def verify_backreferences(obj)
      backreferences = obj.instance_variable_get(:@__weak_backreferences__) if obj.instance_variable_defined?(:@__weak_backreferences__)
      backreferences && backreferences.include?(object_id)
    end
end

require "delegate"

# WeakRef is a class to represent a reference to an object that is not seen by the tracing
# phase of the garbage collector. This allows the referenced object to be garbage collected
# as if nothing is referring to it. Because WeakRef delegates method calls to the referenced
# object, it may be used in place of that object, i.e. it is of the same duck type.
#
# If you don't need to use the delegator pattern, you can use WeakReference instead.
#
# Usage:
#   foo = Object.new
#   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)
class WeakRef < Delegator
  class RefError < StandardError
  end
  
  def initialize(obj)
    super
  end
  
  def __getobj__
    obj = @reference.object
    Kernel::raise(RefError, "Invalid Reference - probably recycled", Kernel::caller(1)) unless obj
    obj
  end
  
  def __setobj__(obj)
    @reference = WeakReference.new(obj)
  end
  
  def weakref_alive?
    !!@reference.object
  end
end

if __FILE__ == $0
  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

In This Thread