Skip to content

Commit 1782462

Browse files
karespitr-ch
authored andcommitted
let's not (potentially) leak context on Java 7
holding a context instance will avoid RubyThread from being gc-d
1 parent 5e18636 commit 1782462

File tree

1 file changed

+9
-8
lines changed

1 file changed

+9
-8
lines changed

ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
public class SynchronizationLibrary implements Library {
2424

2525
private static final Unsafe UNSAFE = loadUnsafe();
26+
private static final boolean FULL_FENCE = supportsFences();
2627

2728
private static Unsafe loadUnsafe() {
2829
try {
@@ -140,17 +141,17 @@ public static class JRubyAttrVolatile {
140141
// volatile threadContext is used as a memory barrier per the JVM memory model happens-before semantic
141142
// on volatile fields. any volatile field could have been used but using the thread context is an
142143
// attempt to avoid code elimination.
143-
private static volatile ThreadContext threadContext = null;
144+
private static volatile int volatileField;
144145

145146
@JRubyMethod(name = "full_memory_barrier", visibility = Visibility.PUBLIC)
146147
public static IRubyObject fullMemoryBarrier(ThreadContext context, IRubyObject self) {
147148
// Prevent reordering of ivar writes with publication of this instance
148-
if (!supportsFences()) {
149+
if (!FULL_FENCE) {
149150
// Assuming that following volatile read and write is not eliminated it simulates fullFence.
150151
// If it's eliminated it'll cause problems only on non-x86 platforms.
151152
// http://shipilev.net/blog/2014/jmm-pragmatics/#_happens_before_test_your_understanding
152-
final ThreadContext oldContext = threadContext;
153-
threadContext = context;
153+
final int volatileRead = volatileField;
154+
volatileField = context.getLine();
154155
} else {
155156
UNSAFE.fullFence();
156157
}
@@ -163,9 +164,9 @@ public static IRubyObject instanceVariableGetVolatile(
163164
IRubyObject self,
164165
IRubyObject name) {
165166
// Ensure we ses latest value with loadFence
166-
if (!supportsFences()) {
167+
if (!FULL_FENCE) {
167168
// piggybacking on volatile read, simulating loadFence
168-
final ThreadContext oldContext = threadContext;
169+
final int volatileRead = volatileField;
169170
return ((RubyBasicObject) self).instance_variable_get(context, name);
170171
} else {
171172
UNSAFE.loadFence();
@@ -180,10 +181,10 @@ public static IRubyObject InstanceVariableSetVolatile(
180181
IRubyObject name,
181182
IRubyObject value) {
182183
// Ensure we make last update visible
183-
if (!supportsFences()) {
184+
if (!FULL_FENCE) {
184185
// piggybacking on volatile write, simulating storeFence
185186
final IRubyObject result = ((RubyBasicObject) self).instance_variable_set(name, value);
186-
threadContext = context;
187+
volatileField = context.getLine();
187188
return result;
188189
} else {
189190
// JRuby uses StampedVariableAccessor which calls fullFence

0 commit comments

Comments
 (0)