class Ref::ReferenceQueue

This class provides a simple thread safe container to hold a reference queue. Instances of WeakReference can be added to the queue and as the objects pointed to by those references are cleaned up by the garbage collector, the references will be added to the queue.

The reason for using a reference queue is that it tends to be more efficient than adding individual finalizers to objects and the cleanup code can be handled by a thread outside of garbage collection.

In general, you should create your own subclass of WeakReference that contains the logic needed to complete the cleanup. The object pointed to will have already been cleaned up and the reference cannot maintain a reference to the object.

Example usage:

class MyRef < Ref::WeakReference
  def cleanup
    # Do something...
  end
end

queue = Ref::ReferenceQueue.new
ref = MyRef.new(Object.new)
queue.monitor(ref)
queue.shift                 # = nil
ObjectSpace.garbage_collect
r = queue.shift             # = ref
r.cleanup

Public Class Methods

new() click to toggle source
# File lib/ref/reference_queue.rb, line 30
def initialize
  @queue = []
  @references = {}
  @lock = Monitor.new
  @finalizer = lambda do |object_id|
    @lock.synchronize do
      ref = @references.delete(object_id)
      @queue.push(ref) if ref
    end
  end
end

Public Instance Methods

empty?() click to toggle source

Return true if the queue is empty.

# File lib/ref/reference_queue.rb, line 80
def empty?
  @queue.empty?
end
monitor(reference) click to toggle source

Monitor a reference. When the object the reference points to is garbage collected, the reference will be added to the queue.

# File lib/ref/reference_queue.rb, line 44
def monitor(reference)
  obj = reference.object
  if obj
    @lock.synchronize do
      @references[reference.referenced_object_id] = reference
    end
    ObjectSpace.define_finalizer(obj, @finalizer)
  else
    push(reference)
  end
end
pop() click to toggle source

Pull the last reference off the queue. Returns nil if their are no references.

# File lib/ref/reference_queue.rb, line 66
def pop
  @lock.synchronize do
    @queue.pop
  end
end
push(reference) click to toggle source

Add a reference to the queue.

# File lib/ref/reference_queue.rb, line 57
def push(reference)
  if reference
    @lock.synchronize do
      @queue.push(reference)
    end
  end
end
shift() click to toggle source

Pull the next reference off the queue. Returns nil if there are no references.

# File lib/ref/reference_queue.rb, line 73
def shift
  @lock.synchronize do
    @queue.shift
  end
end
size() click to toggle source

Get the current size of the queue.

# File lib/ref/reference_queue.rb, line 85
def size
  @queue.size
end