Skip to content

Commit f99fc02

Browse files
committed
Improve Java volatile field support
1 parent 93ce7ec commit f99fc02

File tree

2 files changed

+26
-16
lines changed

2 files changed

+26
-16
lines changed

ext/com/concurrent_ruby/ext/SynchronizationLibrary.java

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
4545
@JRubyClass(name = "JavaObject", parent = "AbstractObject")
4646
public static class JavaObject extends RubyObject {
4747

48-
private volatile int anVolatileField = 0; // TODO unused on JAVA8
49-
5048
public JavaObject(Ruby runtime, RubyClass metaClass) {
5149
super(runtime, metaClass);
5250
}
@@ -118,24 +116,40 @@ public IRubyObject ensureIvarVisibilityBang(ThreadContext context) {
118116
return context.nil;
119117
}
120118

119+
private volatile int anVolatileField = 0; // TODO unused on JAVA8
120+
public static final long AN_VOLATILE_FIELD_OFFSET =
121+
UnsafeHolder.fieldOffset(JavaObject.class, "anVolatileField");
122+
121123
@JRubyMethod(name = "instance_variable_get_volatile", visibility = Visibility.PROTECTED)
122124
public IRubyObject instanceVariableGetVolatile(ThreadContext context, IRubyObject name) {
123-
int tmp;
124-
if (UnsafeHolder.SUPPORTS_FENCES)
125+
if (UnsafeHolder.U == null) {
126+
synchronized (this) {
127+
return instance_variable_get(context, name);
128+
}
129+
} else if (UnsafeHolder.SUPPORTS_FENCES) {
125130
UnsafeHolder.loadFence();
126-
else
127-
tmp = anVolatileField;
128-
return instance_variable_get(context, name);
131+
return instance_variable_get(context, name);
132+
} else {
133+
UnsafeHolder.U.getIntVolatile(this, AN_VOLATILE_FIELD_OFFSET);
134+
return instance_variable_get(context, name);
135+
}
129136
}
130137

131138
@JRubyMethod(name = "instance_variable_set_volatile", visibility = Visibility.PROTECTED)
132139
public IRubyObject InstanceVariableSetVolatile(ThreadContext context, IRubyObject name, IRubyObject value) {
133-
IRubyObject result = instance_variable_set(name, value);
134-
if (UnsafeHolder.SUPPORTS_FENCES)
140+
if (UnsafeHolder.U == null) {
141+
synchronized (this) {
142+
return instance_variable_set(name, value);
143+
}
144+
} else if (UnsafeHolder.SUPPORTS_FENCES) {
145+
IRubyObject result = instance_variable_set(name, value);
135146
UnsafeHolder.storeFence();
136-
else
137-
anVolatileField = 1;
138-
return result;
147+
return result;
148+
} else {
149+
UnsafeHolder.U.putIntVolatile(this, AN_VOLATILE_FIELD_OFFSET, 1);
150+
IRubyObject result = instance_variable_set(name, value);
151+
return result;
152+
}
139153
}
140154
}
141155
}

lib/concurrent/synchronization/java_object.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ module Synchronization
66
if Concurrent.on_jruby?
77
require 'jruby'
88

9-
unless org.jruby.util.unsafe.UnsafeHolder::SUPPORTS_FENCES
10-
raise 'java7 is not supported at the moment, please use java8'
11-
end
12-
139
class JavaObject < AbstractObject
1410

1511
def self.attr_volatile(*names)

0 commit comments

Comments
 (0)