Permalink
Browse files

let's not (potentially) leak context on Java 7

holding a context instance will avoid RubyThread from being gc-d
  • Loading branch information...
kares authored and pitr-ch committed Dec 19, 2018
1 parent 5e18636 commit 17824624a52e4f41c7c0c2a18409152a719cd300
Showing with 9 additions and 8 deletions.
  1. +9 −8 ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java
@@ -23,6 +23,7 @@
public class SynchronizationLibrary implements Library {

private static final Unsafe UNSAFE = loadUnsafe();
private static final boolean FULL_FENCE = supportsFences();

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

@JRubyMethod(name = "full_memory_barrier", visibility = Visibility.PUBLIC)
public static IRubyObject fullMemoryBarrier(ThreadContext context, IRubyObject self) {
// Prevent reordering of ivar writes with publication of this instance
if (!supportsFences()) {
if (!FULL_FENCE) {
// Assuming that following volatile read and write is not eliminated it simulates fullFence.
// If it's eliminated it'll cause problems only on non-x86 platforms.
// http://shipilev.net/blog/2014/jmm-pragmatics/#_happens_before_test_your_understanding
final ThreadContext oldContext = threadContext;
threadContext = context;
final int volatileRead = volatileField;
volatileField = context.getLine();
} else {
UNSAFE.fullFence();
}
@@ -163,9 +164,9 @@ public static IRubyObject instanceVariableGetVolatile(
IRubyObject self,
IRubyObject name) {
// Ensure we ses latest value with loadFence
if (!supportsFences()) {
if (!FULL_FENCE) {
// piggybacking on volatile read, simulating loadFence
final ThreadContext oldContext = threadContext;
final int volatileRead = volatileField;
return ((RubyBasicObject) self).instance_variable_get(context, name);
} else {
UNSAFE.loadFence();
@@ -180,10 +181,10 @@ public static IRubyObject InstanceVariableSetVolatile(
IRubyObject name,
IRubyObject value) {
// Ensure we make last update visible
if (!supportsFences()) {
if (!FULL_FENCE) {
// piggybacking on volatile write, simulating storeFence
final IRubyObject result = ((RubyBasicObject) self).instance_variable_set(name, value);
threadContext = context;
volatileField = context.getLine();
return result;
} else {
// JRuby uses StampedVariableAccessor which calls fullFence

0 comments on commit 1782462

Please sign in to comment.