Skip to content

Commit efa0a9d

Browse files
committed
Do not depend on org.jruby.util.unsafe.UnsafeHolder
1 parent 14a8940 commit efa0a9d

File tree

1 file changed

+56
-28
lines changed

1 file changed

+56
-28
lines changed

ext/com/concurrent_ruby/ext/SynchronizationLibrary.java

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,46 @@
1313
import org.jruby.runtime.Visibility;
1414
import org.jruby.runtime.builtin.IRubyObject;
1515
import org.jruby.runtime.load.Library;
16-
import org.jruby.util.unsafe.UnsafeHolder;
16+
import sun.misc.Unsafe;
1717

1818
import java.io.IOException;
19+
import java.lang.reflect.Field;
1920
import java.lang.reflect.Method;
2021

2122
public class SynchronizationLibrary implements Library {
2223

24+
private static final Unsafe UNSAFE = loadUnsafe();
25+
26+
private static Unsafe loadUnsafe() {
27+
try {
28+
Class ncdfe = Class.forName("sun.misc.Unsafe");
29+
Field f = ncdfe.getDeclaredField("theUnsafe");
30+
f.setAccessible(true);
31+
return (Unsafe) f.get((java.lang.Object) null);
32+
} catch (Exception var2) {
33+
return null;
34+
} catch (NoClassDefFoundError var3) {
35+
return null;
36+
}
37+
}
38+
39+
private static boolean supportsFences() {
40+
if (UNSAFE == null) {
41+
return false;
42+
} else {
43+
try {
44+
Method m = UNSAFE.getClass().getDeclaredMethod("fullFence", new Class[0]);
45+
if (m != null) {
46+
return true;
47+
}
48+
} catch (Exception var1) {
49+
// nothing
50+
}
51+
52+
return false;
53+
}
54+
}
55+
2356
private static final ObjectAllocator JRUBY_OBJECT_ALLOCATOR = new ObjectAllocator() {
2457
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
2558
return new JRubyObject(runtime, klazz);
@@ -65,8 +98,13 @@ public void load(Ruby runtime, boolean wrap) throws IOException {
6598
JRubyLockableObject.class, JRUBY_LOCKABLE_OBJECT_ALLOCATOR);
6699
}
67100

68-
private RubyClass defineClass(Ruby runtime, RubyModule namespace, String parentName, String name,
69-
Class javaImplementation, ObjectAllocator allocator) {
101+
private RubyClass defineClass(
102+
Ruby runtime,
103+
RubyModule namespace,
104+
String parentName,
105+
String name,
106+
Class javaImplementation,
107+
ObjectAllocator allocator) {
70108
final RubyClass parentClass = namespace.getClass(parentName);
71109

72110
if (parentClass == null) {
@@ -90,23 +128,6 @@ private RubyClass defineClass(Ruby runtime, RubyModule namespace, String parentN
90128
// module JRubyAttrVolatile
91129
public static class JRubyAttrVolatile {
92130

93-
private static boolean supportsFences() {
94-
if(UnsafeHolder.U == null) {
95-
return false;
96-
} else {
97-
try {
98-
Method m = UnsafeHolder.U.getClass().getDeclaredMethod("fullFence", new Class[0]);
99-
if(m != null) {
100-
return true;
101-
}
102-
} catch (Exception var1) {
103-
// nothing
104-
}
105-
106-
return false;
107-
}
108-
}
109-
110131
// volatile threadContext is used as a memory barrier per the JVM memory model happens-before semantic
111132
// on volatile fields. any volatile field could have been used but using the thread context is an
112133
// attempt to avoid code elimination.
@@ -122,37 +143,44 @@ public static IRubyObject fullMemoryBarrier(ThreadContext context, IRubyObject s
122143
final ThreadContext oldContext = threadContext;
123144
threadContext = context;
124145
} else {
125-
UnsafeHolder.U.fullFence();
146+
UNSAFE.fullFence();
126147
}
127148
return context.nil;
128149
}
129150

130151
@JRubyMethod(name = "instance_variable_get_volatile", visibility = Visibility.PUBLIC)
131-
public static IRubyObject instanceVariableGetVolatile(ThreadContext context, IRubyObject self, IRubyObject name) {
152+
public static IRubyObject instanceVariableGetVolatile(
153+
ThreadContext context,
154+
IRubyObject self,
155+
IRubyObject name) {
132156
// Ensure we ses latest value with loadFence
133157
if (!supportsFences()) {
134158
// piggybacking on volatile read, simulating loadFence
135159
final ThreadContext oldContext = threadContext;
136-
return ((RubyBasicObject)self).instance_variable_get(context, name);
160+
return ((RubyBasicObject) self).instance_variable_get(context, name);
137161
} else {
138-
UnsafeHolder.U.loadFence();
139-
return ((RubyBasicObject)self).instance_variable_get(context, name);
162+
UNSAFE.loadFence();
163+
return ((RubyBasicObject) self).instance_variable_get(context, name);
140164
}
141165
}
142166

143167
@JRubyMethod(name = "instance_variable_set_volatile", visibility = Visibility.PUBLIC)
144-
public static IRubyObject InstanceVariableSetVolatile(ThreadContext context, IRubyObject self, IRubyObject name, IRubyObject value) {
168+
public static IRubyObject InstanceVariableSetVolatile(
169+
ThreadContext context,
170+
IRubyObject self,
171+
IRubyObject name,
172+
IRubyObject value) {
145173
// Ensure we make last update visible
146174
if (!supportsFences()) {
147175
// piggybacking on volatile write, simulating storeFence
148-
final IRubyObject result = ((RubyBasicObject)self).instance_variable_set(name, value);
176+
final IRubyObject result = ((RubyBasicObject) self).instance_variable_set(name, value);
149177
threadContext = context;
150178
return result;
151179
} else {
152180
// JRuby uses StampedVariableAccessor which calls fullFence
153181
// so no additional steps needed.
154182
// See https://github.com/jruby/jruby/blob/master/core/src/main/java/org/jruby/runtime/ivars/StampedVariableAccessor.java#L151-L159
155-
return ((RubyBasicObject)self).instance_variable_set(name, value);
183+
return ((RubyBasicObject) self).instance_variable_set(name, value);
156184
}
157185
}
158186
}

0 commit comments

Comments
 (0)