2121
2222public class SynchronizationLibrary implements Library {
2323
24+ private static final ObjectAllocator JRUBYREFERENCE_ALLOCATOR = new ObjectAllocator () {
25+ public IRubyObject allocate (Ruby runtime , RubyClass klazz ) {
26+ return new JavaObject (runtime , klazz );
27+ }
28+ };
29+
2430 public void load (Ruby runtime , boolean wrap ) throws IOException {
2531 RubyModule synchronizationModule = runtime .
2632 defineModule ("Concurrent" ).
@@ -36,15 +42,13 @@ public void load(Ruby runtime, boolean wrap) throws IOException {
3642 synchronizedObjectJavaClass .defineAnnotatedMethods (JavaObject .class );
3743 }
3844
39- private static final ObjectAllocator JRUBYREFERENCE_ALLOCATOR = new ObjectAllocator () {
40- public IRubyObject allocate (Ruby runtime , RubyClass klazz ) {
41- return new JavaObject (runtime , klazz );
42- }
43- };
44-
4545 @ JRubyClass (name = "JavaObject" , parent = "AbstractObject" )
4646 public static class JavaObject extends RubyObject {
4747
48+ public static final long AN_VOLATILE_FIELD_OFFSET =
49+ UnsafeHolder .fieldOffset (JavaObject .class , "anVolatileField" );
50+ private volatile int anVolatileField = 0 ;
51+
4852 public JavaObject (Ruby runtime , RubyClass metaClass ) {
4953 super (runtime , metaClass );
5054 }
@@ -107,24 +111,30 @@ public IRubyObject nsBroadcast(ThreadContext context) {
107111
108112 @ JRubyMethod (name = "ensure_ivar_visibility!" , visibility = Visibility .PROTECTED )
109113 public IRubyObject ensureIvarVisibilityBang (ThreadContext context ) {
110- if (UnsafeHolder .SUPPORTS_FENCES )
111- UnsafeHolder .storeFence ();
112- else
113- anVolatileField = 1 ;
114+ if (UnsafeHolder .U == null ) {
115+ // We are screwed
116+ throw new UnsupportedOperationException ();
117+ } else if (UnsafeHolder .SUPPORTS_FENCES )
118+ // We have to prevent ivar writes to reordered with storing of the final instance reference
119+ // Therefore wee need a fullFence to prevent reordering in both directions.
120+ UnsafeHolder .fullFence ();
121+ else {
122+ // Assumption that this is not eliminated, if false it will break non x86 platforms.
123+ UnsafeHolder .U .putIntVolatile (this , AN_VOLATILE_FIELD_OFFSET , 1 );
124+ UnsafeHolder .U .getIntVolatile (this , AN_VOLATILE_FIELD_OFFSET );
125+ }
114126 return context .nil ;
115127 }
116128
117- private volatile int anVolatileField = 0 ; // TODO unused on JAVA8
118- public static final long AN_VOLATILE_FIELD_OFFSET =
119- UnsafeHolder .fieldOffset (JavaObject .class , "anVolatileField" );
120-
121129 @ JRubyMethod (name = "instance_variable_get_volatile" , visibility = Visibility .PROTECTED )
122130 public IRubyObject instanceVariableGetVolatile (ThreadContext context , IRubyObject name ) {
123131 if (UnsafeHolder .U == null ) {
132+ // TODO: Possibly dangerous, there may be a deadlock on the this
124133 synchronized (this ) {
125134 return instance_variable_get (context , name );
126135 }
127136 } else if (UnsafeHolder .SUPPORTS_FENCES ) {
137+ // ensure we see latest value
128138 UnsafeHolder .loadFence ();
129139 return instance_variable_get (context , name );
130140 } else {
@@ -136,16 +146,18 @@ public IRubyObject instanceVariableGetVolatile(ThreadContext context, IRubyObjec
136146 @ JRubyMethod (name = "instance_variable_set_volatile" , visibility = Visibility .PROTECTED )
137147 public IRubyObject InstanceVariableSetVolatile (ThreadContext context , IRubyObject name , IRubyObject value ) {
138148 if (UnsafeHolder .U == null ) {
149+ // TODO: Possibly dangerous, there may be a deadlock on the this
139150 synchronized (this ) {
140151 return instance_variable_set (name , value );
141152 }
142153 } else if (UnsafeHolder .SUPPORTS_FENCES ) {
143- IRubyObject result = instance_variable_set (name , value );
154+ final IRubyObject result = instance_variable_set (name , value );
155+ // ensure we make latest value visible
144156 UnsafeHolder .storeFence ();
145157 return result ;
146158 } else {
159+ final IRubyObject result = instance_variable_set (name , value );
147160 UnsafeHolder .U .putIntVolatile (this , AN_VOLATILE_FIELD_OFFSET , 1 );
148- IRubyObject result = instance_variable_set (name , value );
149161 return result ;
150162 }
151163 }
0 commit comments