Skip to content
This repository was archived by the owner on Mar 15, 2022. It is now read-only.

Replaces SafeMonitor with Ruby's Monitor #21

Merged
merged 1 commit into from
Feb 9, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion lib/ref.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module Ref
require 'ref/abstract_reference_key_map'
require 'ref/reference'
require 'ref/reference_queue'
require 'ref/safe_monitor'

# Set the best implementation for weak references based on the runtime.
if defined?(RUBY_PLATFORM) && RUBY_PLATFORM == 'java'
Expand Down
12 changes: 6 additions & 6 deletions lib/ref/abstract_reference_key_map.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ class << self
def reference_class=(klass) #:nodoc:
@reference_class = klass
end

def reference_class #:nodoc:
raise NotImplementedError.new("#{name} is an abstract class and cannot be instantiated") unless @reference_class
@reference_class
end
end

# Create a new map. Values added to the hash will be cleaned up by the garbage
# collector if there are no other reference except in the map.
def initialize
@values = {}
@references_to_keys_map = {}
@lock = SafeMonitor.new
@lock = Monitor.new
@reference_cleanup = lambda{|object_id| remove_reference_to(object_id)}
end

Expand Down Expand Up @@ -60,14 +60,14 @@ def delete(key)
def keys
@values.keys.collect{|rkey| @references_to_keys_map[rkey].object}.compact
end

# Turn the map into an arry of [key, value] entries.
def to_a
array = []
each{|k,v| array << [k, v]}
array
end

# Iterate through all the key/value pairs in the map that have not been reclaimed
# by the garbage collector.
def each
Expand Down Expand Up @@ -128,7 +128,7 @@ def ref_key (key)
nil
end
end

def remove_reference_to(object_id)
@lock.synchronize do
@references_to_keys_map.delete(object_id)
Expand Down
10 changes: 5 additions & 5 deletions lib/ref/abstract_reference_value_map.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ class << self
def reference_class=(klass) #:nodoc:
@reference_class = klass
end

def reference_class #:nodoc:
raise NotImplementedError.new("#{name} is an abstract class and cannot be instantiated") unless @reference_class
@reference_class
end
end

# Create a new map. Values added to the map will be cleaned up by the garbage
# collector if there are no other reference except in the map.
def initialize
@references = {}
@references_to_keys_map = {}
@lock = SafeMonitor.new
@lock = Monitor.new
@reference_cleanup = lambda{|object_id| remove_reference_to(object_id)}
end

Expand Down Expand Up @@ -74,14 +74,14 @@ def values
each{|k,v| vals << v}
vals
end

# Turn the map into an arry of [key, value] entries
def to_a
array = []
each{|k,v| array << [k, v]}
array
end

# Iterate through all the key/value pairs in the map that have not been reclaimed
# by the garbage collector.
def each
Expand Down
16 changes: 8 additions & 8 deletions lib/ref/reference_queue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module Ref
# # Do something...
# end
# end
#
#
# queue = Ref::ReferenceQueue.new
# ref = MyRef.new(Object.new)
# queue.monitor(ref)
Expand All @@ -30,15 +30,15 @@ class ReferenceQueue
def initialize
@queue = []
@references = {}
@lock = SafeMonitor.new
@lock = Monitor.new
@finalizer = lambda do |object_id|
@lock.synchronize do
ref = @references.delete(object_id)
@queue.push(ref) if ref
end
end
end

# Monitor a reference. When the object the reference points to is garbage collected,
# the reference will be added to the queue.
def monitor(reference)
Expand All @@ -52,7 +52,7 @@ def monitor(reference)
push(reference)
end
end

# Add a reference to the queue.
def push(reference)
if reference
Expand All @@ -61,26 +61,26 @@ def push(reference)
end
end
end

# Pull the last reference off the queue. Returns +nil+ if their are no references.
def pop
@lock.synchronize do
@queue.pop
end
end

# Pull the next reference off the queue. Returns +nil+ if there are no references.
def shift
@lock.synchronize do
@queue.shift
end
end

# Return +true+ if the queue is empty.
def empty?
@queue.empty?
end

# Get the current size of the queue.
def size
@queue.size
Expand Down
50 changes: 0 additions & 50 deletions lib/ref/safe_monitor.rb

This file was deleted.

14 changes: 7 additions & 7 deletions lib/ref/soft_reference.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ module Ref
class SoftReference < Reference
@@strong_references = [{}]
@@gc_flag_set = false

# Number of garbage collection cycles after an object is used before a reference to it can be reclaimed.
MIN_GC_CYCLES = 10
@@lock = SafeMonitor.new

@@lock = Monitor.new

@@finalizer = lambda do |object_id|
@@lock.synchronize do
while @@strong_references.size >= MIN_GC_CYCLES do
Expand All @@ -34,14 +34,14 @@ class SoftReference < Reference
@@gc_flag_set = false
end
end

# Create a new soft reference to an object.
def initialize(obj)
@referenced_object_id = obj.__id__
@weak_reference = WeakReference.new(obj)
add_strong_reference(obj)
end

# Get the referenced object. If the object has been reclaimed by the
# garbage collector, then this will return nil.
def object
Expand All @@ -50,7 +50,7 @@ def object
add_strong_reference(obj) if obj
obj
end

private
# Create a strong reference to the object. This reference will live
# for three passes of the garbage collector.
Expand Down
18 changes: 9 additions & 9 deletions lib/ref/weak_reference/pure_ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,33 @@ module Ref
# subclass Delegator which is very heavy to instantiate and utilizes a
# because it does not fair amount of memory under Ruby 1.8.
class WeakReference < Reference

class ReferencePointer
def initialize(object)
@referenced_object_id = object.__id__
add_backreference(object)
end

def cleanup
obj = ObjectSpace._id2ref(@referenced_object_id) rescue nil
remove_backreference(obj) if obj
end

def object
obj = ObjectSpace._id2ref(@referenced_object_id)
obj if verify_backreferences(obj)
rescue RangeError
nil
end

private
# Verify that the object is the same one originally set for the weak reference.
def verify_backreferences(obj) #:nodoc:
return nil unless supports_backreference?(obj)
backreferences = obj.instance_variable_get(:@__weak_backreferences__) if obj.instance_variable_defined?(:@__weak_backreferences__)
backreferences && backreferences.include?(object_id)
end

# Add a backreference to the object.
def add_backreference(obj) #:nodoc:
return unless supports_backreference?(obj)
Expand All @@ -41,7 +41,7 @@ def add_backreference(obj) #:nodoc:
end
backreferences << object_id
end

# Remove backreferences from the object.
def remove_backreference(obj) #:nodoc:
return unless supports_backreference?(obj)
Expand All @@ -51,16 +51,16 @@ def remove_backreference(obj) #:nodoc:
obj.send(:remove_instance_variable, :@__weak_backreferences__) if backreferences.empty?
end
end

def supports_backreference?(obj)
obj.respond_to?(:instance_variable_get) && obj.respond_to?(:instance_variable_defined?)
rescue NoMethodError
false
end
end

@@weak_references = {}
@@lock = SafeMonitor.new
@@lock = Monitor.new

# Finalizer that cleans up weak references when references are destroyed.
@@reference_finalizer = lambda do |object_id|
Expand Down