diff --git a/ext/java/org/jruby/ext/ref/ReferencesService.java b/ext/java/org/jruby/ext/ref/ReferencesService.java new file mode 100644 index 0000000..5ef38f8 --- /dev/null +++ b/ext/java/org/jruby/ext/ref/ReferencesService.java @@ -0,0 +1,28 @@ +package org.jruby.ext.ref; + +import java.io.IOException; +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.runtime.load.BasicLibraryService; + +/** + * This library adds native Java support for weak and soft references. + * + * @author Brian Durand + */ +public class ReferencesService implements BasicLibraryService { + public boolean basicLoad(Ruby runtime) throws IOException { + RubyModule refModule = runtime.getModule("Ref"); + RubyClass referenceClass = refModule.getClass("Reference"); + + RubyClass rubyWeakReferenceClass = runtime.defineClassUnder("WeakReference", referenceClass, RubyWeakReference.ALLOCATOR, refModule); + rubyWeakReferenceClass.defineAnnotatedMethods(RubyWeakReference.class); + + RubyClass rubySoftReferenceClass = runtime.defineClassUnder("SoftReference", referenceClass, RubySoftReference.ALLOCATOR, refModule); + rubySoftReferenceClass.defineAnnotatedMethods(RubySoftReference.class); + + return true; + } +} diff --git a/ext/java/org/jruby/ext/ref/RubySoftReference.java b/ext/java/org/jruby/ext/ref/RubySoftReference.java new file mode 100644 index 0000000..55690fc --- /dev/null +++ b/ext/java/org/jruby/ext/ref/RubySoftReference.java @@ -0,0 +1,43 @@ +package org.jruby.ext.ref; + +import java.lang.ref.SoftReference; +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyObject; +import org.jruby.anno.JRubyMethod; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.Visibility; + +public class RubySoftReference extends RubyObject { + private SoftReference _ref; + private static final String REFERENCED_OBJECT_ID_VARIABLE = "@referenced_object_id".intern(); + + public RubySoftReference(Ruby runtime, RubyClass klass) { + super(runtime, klass); + } + + public static final ObjectAllocator ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new RubySoftReference(runtime, klass); + } + }; + + @JRubyMethod(name = "initialize", frame = true, visibility = Visibility.PRIVATE) + public IRubyObject initialize(ThreadContext context, IRubyObject obj) { + _ref = new SoftReference(obj); + fastSetInstanceVariable(REFERENCED_OBJECT_ID_VARIABLE, obj.id()); + return context.getRuntime().getNil(); + } + + @JRubyMethod(name = "object") + public IRubyObject object() { + IRubyObject obj = (IRubyObject)_ref.get(); + if (obj != null) { + return obj; + } else { + return getRuntime().getNil(); + } + } +} diff --git a/ext/java/org/jruby/ext/ref/RubyWeakReference.java b/ext/java/org/jruby/ext/ref/RubyWeakReference.java new file mode 100644 index 0000000..2e9b0f2 --- /dev/null +++ b/ext/java/org/jruby/ext/ref/RubyWeakReference.java @@ -0,0 +1,43 @@ +package org.jruby.ext.ref; + +import java.lang.ref.WeakReference; +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyObject; +import org.jruby.anno.JRubyMethod; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.Visibility; + +public class RubyWeakReference extends RubyObject { + private WeakReference _ref; + private static final String REFERENCED_OBJECT_ID_VARIABLE = "@referenced_object_id".intern(); + + public RubyWeakReference(Ruby runtime, RubyClass klass) { + super(runtime, klass); + } + + public static final ObjectAllocator ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new RubyWeakReference(runtime, klass); + } + }; + + @JRubyMethod(name = "initialize", frame = true, visibility = Visibility.PRIVATE) + public IRubyObject initialize(ThreadContext context, IRubyObject obj) { + _ref = new WeakReference(obj); + fastSetInstanceVariable(REFERENCED_OBJECT_ID_VARIABLE, obj.id()); + return context.getRuntime().getNil(); + } + + @JRubyMethod(name = "object") + public IRubyObject object() { + IRubyObject obj = (IRubyObject)_ref.get(); + if (obj != null) { + return obj; + } else { + return getRuntime().getNil(); + } + } +} diff --git a/lib/org/jruby/ext/ref/references.jar b/lib/org/jruby/ext/ref/references.jar new file mode 100644 index 0000000..171d717 Binary files /dev/null and b/lib/org/jruby/ext/ref/references.jar differ diff --git a/lib/ref.rb b/lib/ref.rb index f61c752..f483ea2 100644 --- a/lib/ref.rb +++ b/lib/ref.rb @@ -7,11 +7,13 @@ module Ref # Set the best implementation for weak references based on the runtime. if defined?(RUBY_PLATFORM) && RUBY_PLATFORM == 'java' - $LOAD_PATH.unshift(File.dirname(__FILE__)) - require 'ref/jruby/weak_reference' - require 'ref/jruby/soft_reference' - - $LOAD_PATH.shift if $LOAD_PATH.first == File.dirname(__FILE__) + # Use native Java references + begin + $LOAD_PATH.unshift(File.dirname(__FILE__)) + require 'org/jruby/ext/ref/references' + ensure + $LOAD_PATH.shift if $LOAD_PATH.first == File.dirname(__FILE__) + end else require 'ref/soft_reference' if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' diff --git a/lib/ref/jruby/soft_reference.rb b/lib/ref/jruby/soft_reference.rb deleted file mode 100644 index 941a392..0000000 --- a/lib/ref/jruby/soft_reference.rb +++ /dev/null @@ -1,13 +0,0 @@ -module Ref - - class SoftReference < Reference - def initialize(obj) - @_ref = java.lang.ref.SoftReference.new(obj) - @referenced_object_id = obj.__id__ - end - - def object - @_ref.get() - end - end -end diff --git a/lib/ref/jruby/weak_reference.rb b/lib/ref/jruby/weak_reference.rb deleted file mode 100644 index a08d10a..0000000 --- a/lib/ref/jruby/weak_reference.rb +++ /dev/null @@ -1,15 +0,0 @@ -module Ref - class WeakReference < Reference - - def initialize(obj) - @_ref = java.lang.ref.WeakReference.new(obj) - @referenced_object_id = obj.__id__ - end - - def object - @_ref.get() - end - - end - -end