2012-08-11 12:26:14 -05:00
|
|
|
module V8
|
|
|
|
module Weak
|
|
|
|
# weak refs are broken on MRI 1.9 and merely slow on 1.8
|
|
|
|
# so we mitigate this by using the 'ref' gem. However, this
|
|
|
|
# only mitigates the problem. Under heavy load, you will still
|
2013-02-25 21:59:45 -06:00
|
|
|
# get different or terminated objects being returned. bad stuff.
|
|
|
|
#
|
|
|
|
# If you are having problems with this, an upgrade to 2.0 is *highly*
|
|
|
|
# recommended.
|
2012-08-11 12:26:14 -05:00
|
|
|
#
|
|
|
|
# for other platforms we just use the stdlib 'weakref'
|
|
|
|
# implementation
|
2013-02-25 21:59:45 -06:00
|
|
|
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ruby' && RUBY_VERSION < '2.0.0'
|
2012-08-11 12:26:14 -05:00
|
|
|
require 'ref'
|
|
|
|
Ref = ::Ref::WeakReference
|
|
|
|
WeakValueMap = ::Ref::WeakValueMap
|
|
|
|
else
|
|
|
|
require 'weakref'
|
|
|
|
class Ref
|
|
|
|
def initialize(object)
|
|
|
|
@ref = ::WeakRef.new(object)
|
|
|
|
end
|
|
|
|
def object
|
|
|
|
@ref.__getobj__
|
|
|
|
rescue ::WeakRef::RefError
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class WeakValueMap
|
|
|
|
def initialize
|
|
|
|
@values = {}
|
|
|
|
end
|
|
|
|
|
|
|
|
def [](key)
|
|
|
|
if ref = @values[key]
|
|
|
|
ref.object
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def []=(key, value)
|
|
|
|
@values[key] = V8::Weak::Ref.new(value)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module Cell
|
|
|
|
def weakcell(name, &block)
|
|
|
|
unless storage = instance_variable_get("@#{name}")
|
|
|
|
storage = instance_variable_set("@#{name}", Storage.new)
|
|
|
|
end
|
|
|
|
storage.access(&block)
|
|
|
|
end
|
|
|
|
class Storage
|
|
|
|
def access(&block)
|
|
|
|
if @ref
|
|
|
|
@ref.object || populate(block)
|
|
|
|
else
|
|
|
|
populate(block)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def populate(block)
|
|
|
|
occupant = block.call()
|
|
|
|
@ref = V8::Weak::Ref.new(occupant)
|
|
|
|
return occupant
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|