Skip to content
Permalink
Browse files
Use atomic references for completed Java proxy class/module.
  • Loading branch information
headius committed Feb 26, 2015
1 parent e53e2cb commit 7f4f43c6fc769ac48983e0907bce42a9584b514c
@@ -52,6 +52,7 @@
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;

import org.jruby.Ruby;
@@ -119,11 +120,11 @@ public class JavaClass extends JavaObject {
private volatile ArrayList<IRubyObject> proxyExtenders;

// proxy module for interfaces
public volatile RubyModule proxyModule;
public final AtomicReference<RubyModule> proxyModule = new AtomicReference<RubyModule>();

// proxy class for concrete classes. also used for
// "concrete" interfaces, which is why we have two fields
public volatile RubyClass proxyClass;
public final AtomicReference<RubyClass> proxyClass = new AtomicReference<RubyClass>();

// readable only by thread building proxy, so don't need to be
// volatile. used to handle recursive calls to getProxyClass/Module
@@ -140,7 +141,7 @@ public RubyModule getProxyModule() {
// allow proxy to be read without synchronization. if proxy
// is under construction, only the building thread can see it.
RubyModule proxy;
if ((proxy = proxyModule) != null) {
if ((proxy = proxyModule.get()) != null) {
// proxy is complete, return it
return proxy;
} else if (proxyLock.isHeldByCurrentThread()) {
@@ -155,7 +156,7 @@ public RubyClass getProxyClass() {
// allow proxy to be read without synchronization. if proxy
// is under construction, only the building thread can see it.
RubyClass proxy;
if ((proxy = proxyClass) != null) {
if ((proxy = proxyClass.get()) != null) {
// proxy is complete, return it
return proxy;
} else if (proxyLock.isHeldByCurrentThread()) {
@@ -242,7 +243,7 @@ public void applyProxyExtenders() {
}

private void extendProxy(IRubyObject extender) {
extender.callMethod(getRuntime().getCurrentContext(), "extend_proxy", proxyModule);
extender.callMethod(getRuntime().getCurrentContext(), "extend_proxy", proxyModule.get());
}

@JRubyMethod(required = 1)
@@ -64,12 +64,11 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz

proxyClass.setReifiedClass(javaClass);

assert javaClassObject.proxyClass == null;
javaClassObject.unfinishedProxyClass = proxyClass;
if (javaClass.isArray() || javaClass.isPrimitive()) {
// see note below re: 2-field kludge
javaClassObject.proxyClass = proxyClass;
javaClassObject.proxyModule = proxy;
javaClassObject.proxyClass.compareAndSet(null, proxyClass);
javaClassObject.proxyModule.compareAndSet(null, proxy);
return;
}

@@ -97,8 +96,8 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
// FIXME: bit of a kludge here (non-interface classes assigned to both
// class and module fields). simplifies proxy extender code, will go away
// when JI is overhauled (and proxy extenders are deprecated).
javaClassObject.proxyClass = proxyClass;
javaClassObject.proxyModule = proxy;
javaClassObject.proxyClass.compareAndSet(null, proxyClass);
javaClassObject.proxyModule.compareAndSet(null, proxy);

javaClassObject.applyProxyExtenders();

@@ -67,7 +67,7 @@ public synchronized void initialize(JavaClass javaClassObject, RubyModule module
module.setJavaProxy(true);
module.getSingletonClass().setJavaProxy(true);

javaClassObject.proxyModule = module;
javaClassObject.proxyModule.compareAndSet(null, module);
javaClassObject.applyProxyExtenders();
}

0 comments on commit 7f4f43c

Please sign in to comment.