From: email@... Date: 2016-05-19T21:02:33+00:00 Subject: [ruby-core:75620] [CommonRuby Feature#12021] Final instance variables Issue #12021 has been updated by Petr Chalupa. Consider following code: ~~~ ruby QUEUE = Queue.new WORKER = Thread.new { loop { QUEUE.pop.call } } def async(&job) QUEUE.push job nil end def the_example local_var = :value async { p local_var } end ~~~ Currently by RMM rules and on current implementations there is no documented guarantee that the job executed asynchronously will print the :value. (JRuby actually documents and warns that it may not print :value). (It safe on MRI because of undocumented behavior of GIL.) This behavior is quite inconvenient. It requires that APIs for threads, fibers and other concurrent libraries (e.g. async, promises) need to pass the values to the block through the factory methods as follows and internally ensure visibility. ~~~ ruby Thread.new(local_var) { |v| p v } async(local_var) { |v| p v } # etc. ~~~ Using this proposal also for Proc and its hidden field which holds the captured scope could be used to fix this issue. If the hidden field holding scope of Proc is classified as final then it implies that any of the local variable assignments before the Proc construction cannot be reordered with publishing of the proc instance. Therefore when the proc is executed on a different thread it's guaranteed that the values in captured local variables assigned before the proc construction will be visible. Therefore following would be correct and safe: ~~~ ruby local_var = :value Thread.new { p local_var } async { p local_var } ~~~ In relation to discussion happening in https://bugs.ruby-lang.org/issues/12020, where is being discussed distinction between low and high level documentation: The explanation above would fall into the low-level part, high-level documentation for users of Proc would simply say that: "When Proc is created it captures local variables and theirs latest values in the scope. (Subsequent updates to local variables may or may not be visible to the Proc's body.)". The visibility of values assigned before the Proc instance creation is currently expected behavior due to GIL undocumented behavior. ---------------------------------------- Feature #12021: Final instance variables https://bugs.ruby-lang.org/issues/12021#change-58751 * Author: Petr Chalupa * Status: Open * Priority: Normal * Assignee: ---------------------------------------- Having a final instance variables in Ruby will allow: to construct thread-save immutable objects without additional synchronisation on instance variable reading ~~~ ruby # Immutable and thread-safe class TreeNode attr :left, :right, :value, final: true attr_reader :left, :right, :value def initialize(left, right, value) @left, @right, @value = left, right, value end end ~~~ And to fix the an issue shown in the following example: ~~~ ruby attr :lock, final: true def initialize @lock = Mutex.new # ... end def a_protected_method @lock.synchronize do # ... end end ~~~ The issue lies in initialization of instance variable `@lock` which is not ensured to be visible in subsequent call to `a_protected_method` method on a different thread. Summary can be found in this document https://docs.google.com/document/d/1c07qfDArx0bhK9sMr24elaIUdOGudiqBhTIRALEbrYY/edit#. The aggregating issue of this effort can be found [here](https://bugs.ruby-lang.org/issues/12019). -- https://bugs.ruby-lang.org/ Unsubscribe: