concurrent-ruby 1.0.5 → 1.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +115 -0
  3. data/Gemfile +42 -0
  4. data/{LICENSE.txt → LICENSE.md} +2 -0
  5. data/README.md +242 -105
  6. data/Rakefile +332 -0
  7. data/ext/concurrent-ruby/ConcurrentRubyService.java +17 -0
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +175 -0
  9. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java +248 -0
  10. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java +93 -0
  11. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +113 -0
  12. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +159 -0
  13. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +307 -0
  14. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMap.java +31 -0
  15. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +3863 -0
  16. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/LongAdder.java +203 -0
  17. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/Striped64.java +342 -0
  18. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +3800 -0
  19. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java +204 -0
  20. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java +291 -0
  21. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java +199 -0
  22. data/lib/concurrent-ruby/concurrent-ruby.rb +1 -0
  23. data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +24 -20
  24. data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +7 -7
  25. data/lib/concurrent-ruby/concurrent/array.rb +66 -0
  26. data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +18 -4
  27. data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +10 -10
  28. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/abstract_thread_local_var.rb +0 -0
  29. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +26 -22
  30. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +27 -23
  31. data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +164 -0
  32. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +204 -0
  33. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +7 -7
  34. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +1 -1
  35. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +1 -1
  36. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +9 -6
  37. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_thread_local_var.rb +0 -0
  38. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +2 -0
  39. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +0 -0
  40. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +1 -0
  41. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +0 -0
  42. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +2 -1
  43. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +3 -1
  44. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/ruby_thread_local_var.rb +43 -33
  45. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +8 -8
  46. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/thread_local_var.rb +8 -8
  47. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +3 -8
  48. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +1 -1
  49. data/lib/concurrent-ruby/concurrent/atomics.rb +10 -0
  50. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +0 -0
  51. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +0 -0
  52. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
  53. data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +158 -0
  54. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +3 -3
  55. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +0 -0
  56. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +1 -2
  57. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
  58. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +30 -30
  59. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +0 -0
  60. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
  61. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +3 -3
  62. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/logging.rb +6 -1
  63. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
  64. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +7 -7
  65. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  66. data/lib/{concurrent → concurrent-ruby/concurrent}/configuration.rb +15 -15
  67. data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +1 -1
  68. data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +2 -1
  69. data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +9 -7
  70. data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +0 -0
  71. data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +21 -25
  72. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +19 -25
  73. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +5 -5
  74. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +17 -17
  75. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +27 -30
  76. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
  77. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
  78. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +19 -16
  79. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
  80. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +12 -8
  81. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +0 -2
  82. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
  83. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +9 -4
  84. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +0 -0
  85. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
  86. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +0 -0
  87. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
  88. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +1 -1
  89. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +3 -2
  90. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +6 -6
  91. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +14 -17
  92. data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
  93. data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +4 -1
  94. data/lib/concurrent-ruby/concurrent/hash.rb +59 -0
  95. data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +8 -0
  96. data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +5 -6
  97. data/lib/concurrent-ruby/concurrent/map.rb +337 -0
  98. data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +1 -1
  99. data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +25 -14
  100. data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +2 -2
  101. data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
  102. data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +53 -21
  103. data/lib/concurrent-ruby/concurrent/promises.rb +2167 -0
  104. data/lib/concurrent-ruby/concurrent/re_include.rb +58 -0
  105. data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +0 -0
  106. data/lib/concurrent-ruby/concurrent/set.rb +66 -0
  107. data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +11 -0
  108. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization.rb +4 -5
  109. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +5 -5
  110. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +0 -0
  111. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +18 -4
  112. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +2 -0
  113. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +0 -0
  114. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_object.rb +1 -0
  115. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +2 -0
  116. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +6 -6
  117. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mri_object.rb +1 -0
  118. data/lib/{concurrent/synchronization/mri_lockable_object.rb → concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb} +19 -14
  119. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +53 -23
  120. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_lockable_object.rb +0 -0
  121. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_object.rb +1 -0
  122. data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +47 -0
  123. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/volatile.rb +11 -9
  124. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/synchronized_delegator.rb +0 -0
  125. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
  126. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
  127. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +0 -0
  128. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +63 -0
  129. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
  130. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +9 -4
  131. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
  132. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
  133. data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +5 -2
  134. data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +1 -1
  135. data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +2 -2
  136. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +4 -4
  137. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/monotonic_time.rb +3 -3
  138. data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +79 -0
  139. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +0 -0
  140. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/processor_counter.rb +5 -2
  141. data/lib/concurrent-ruby/concurrent/version.rb +3 -0
  142. metadata +146 -131
  143. data/lib/concurrent/array.rb +0 -39
  144. data/lib/concurrent/atomic/atomic_reference.rb +0 -51
  145. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +0 -8
  146. data/lib/concurrent/atomic_reference/direct_update.rb +0 -81
  147. data/lib/concurrent/atomic_reference/jruby+truffle.rb +0 -2
  148. data/lib/concurrent/atomic_reference/jruby.rb +0 -16
  149. data/lib/concurrent/atomic_reference/rbx.rb +0 -22
  150. data/lib/concurrent/atomic_reference/ruby.rb +0 -32
  151. data/lib/concurrent/atomics.rb +0 -53
  152. data/lib/concurrent/edge.rb +0 -26
  153. data/lib/concurrent/hash.rb +0 -36
  154. data/lib/concurrent/lazy_register.rb +0 -81
  155. data/lib/concurrent/map.rb +0 -240
  156. data/lib/concurrent/synchronization/truffle_lockable_object.rb +0 -9
  157. data/lib/concurrent/synchronization/truffle_object.rb +0 -31
  158. data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +0 -30
  159. data/lib/concurrent/utility/at_exit.rb +0 -97
  160. data/lib/concurrent/utility/native_extension_loader.rb +0 -73
  161. data/lib/concurrent/version.rb +0 -4
@@ -10,9 +10,10 @@ module Concurrent
10
10
  JRubyObject
11
11
  when Concurrent.on_rbx?
12
12
  RbxObject
13
- when Concurrent.on_truffle?
14
- TruffleObject
13
+ when Concurrent.on_truffleruby?
14
+ TruffleRubyObject
15
15
  else
16
+ warn 'Possibly unsupported Ruby implementation'
16
17
  MriObject
17
18
  end
18
19
  private_constant :ObjectImplementation
@@ -26,15 +27,15 @@ module Concurrent
26
27
 
27
28
  # @!method self.attr_volatile(*names)
28
29
  # Creates methods for reading and writing (as `attr_accessor` does) to a instance variable with
29
- # volatile (Java) semantic. The instance variable should be accessed oly through generated methods.
30
+ # volatile (Java) semantic. The instance variable should be accessed only through generated methods.
30
31
  #
31
- # @param [Array<Symbol>] names of the instance variables to be volatile
32
- # @return [Array<Symbol>] names of defined method names
32
+ # @param [::Array<Symbol>] names of the instance variables to be volatile
33
+ # @return [::Array<Symbol>] names of defined method names
33
34
 
34
35
  # Has to be called by children.
35
36
  def initialize
36
37
  super
37
- initialize_volatile_with_cas
38
+ __initialize_atomic_fields__
38
39
  end
39
40
 
40
41
  # By calling this method on a class, it and all its children are marked to be constructed safely. Meaning that
@@ -48,10 +49,12 @@ module Concurrent
48
49
  # @AFinalValue = 'value' # published safely, does not have to be synchronized
49
50
  # end
50
51
  # end
52
+ # @return [true]
51
53
  def self.safe_initialization!
52
54
  # define only once, and not again in children
53
55
  return if safe_initialization?
54
56
 
57
+ # @!visibility private
55
58
  def self.new(*args, &block)
56
59
  object = super(*args, &block)
57
60
  ensure
@@ -69,6 +72,8 @@ module Concurrent
69
72
 
70
73
  # For testing purposes, quite slow. Injects assert code to new method which will raise if class instance contains
71
74
  # any instance variables with CamelCase names and isn't {.safe_initialization?}.
75
+ # @raise when offend found
76
+ # @return [true]
72
77
  def self.ensure_safe_initialization_when_final_fields_are_present
73
78
  Object.class_eval do
74
79
  def self.new(*args, &block)
@@ -80,6 +85,7 @@ module Concurrent
80
85
  end
81
86
  end
82
87
  end
88
+ true
83
89
  end
84
90
 
85
91
  # Creates methods for reading and writing to a instance variable with
@@ -88,13 +94,30 @@ module Concurrent
88
94
  # This method generates following methods: `value`, `value=(new_value) #=> new_value`,
89
95
  # `swap_value(new_value) #=> old_value`,
90
96
  # `compare_and_set_value(expected, value) #=> true || false`, `update_value(&block)`.
91
- # @param [Array<Symbol>] names of the instance variables to be volatile with CAS.
92
- # @return [Array<Symbol>] names of defined method names.
97
+ # @param [::Array<Symbol>] names of the instance variables to be volatile with CAS.
98
+ # @return [::Array<Symbol>] names of defined method names.
99
+ # @!macro attr_atomic
100
+ # @!method $1
101
+ # @return [Object] The $1.
102
+ # @!method $1=(new_$1)
103
+ # Set the $1.
104
+ # @return [Object] new_$1.
105
+ # @!method swap_$1(new_$1)
106
+ # Set the $1 to new_$1 and return the old $1.
107
+ # @return [Object] old $1
108
+ # @!method compare_and_set_$1(expected_$1, new_$1)
109
+ # Sets the $1 to new_$1 if the current $1 is expected_$1
110
+ # @return [true, false]
111
+ # @!method update_$1(&block)
112
+ # Updates the $1 using the block.
113
+ # @yield [Object] Calculate a new $1 using given (old) $1
114
+ # @yieldparam [Object] old $1
115
+ # @return [Object] new $1
93
116
  def self.attr_atomic(*names)
94
- @volatile_cas_fields ||= []
95
- @volatile_cas_fields += names
117
+ @__atomic_fields__ ||= []
118
+ @__atomic_fields__ += names
96
119
  safe_initialization!
97
- define_initialize_volatile_with_cas
120
+ define_initialize_atomic_fields
98
121
 
99
122
  names.each do |name|
100
123
  ivar = :"@Atomic#{name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }}"
@@ -123,29 +146,36 @@ module Concurrent
123
146
  names.flat_map { |n| [n, :"#{n}=", :"swap_#{n}", :"compare_and_set_#{n}", :"update_#{n}"] }
124
147
  end
125
148
 
126
- # @param [true,false] inherited should inherited volatile with CAS fields be returned?
127
- # @return [Array<Symbol>] Returns defined volatile with CAS fields on this class.
128
- def self.volatile_cas_fields(inherited = true)
129
- @volatile_cas_fields ||= []
130
- ((superclass.volatile_cas_fields if superclass.respond_to?(:volatile_cas_fields) && inherited) || []) +
131
- @volatile_cas_fields
149
+ # @param [true, false] inherited should inherited volatile with CAS fields be returned?
150
+ # @return [::Array<Symbol>] Returns defined volatile with CAS fields on this class.
151
+ def self.atomic_attributes(inherited = true)
152
+ @__atomic_fields__ ||= []
153
+ ((superclass.atomic_attributes if superclass.respond_to?(:atomic_attributes) && inherited) || []) + @__atomic_fields__
154
+ end
155
+
156
+ # @return [true, false] is the attribute with name atomic?
157
+ def self.atomic_attribute?(name)
158
+ atomic_attributes.include? name
132
159
  end
133
160
 
134
161
  private
135
162
 
136
- def self.define_initialize_volatile_with_cas
137
- assignments = @volatile_cas_fields.map { |name| "@Atomic#{name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }} = AtomicReference.new(nil)" }.join("\n")
138
- class_eval <<-RUBY
139
- def initialize_volatile_with_cas
163
+ def self.define_initialize_atomic_fields
164
+ assignments = @__atomic_fields__.map do |name|
165
+ "@Atomic#{name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }} = Concurrent::AtomicReference.new(nil)"
166
+ end.join("\n")
167
+
168
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
169
+ def __initialize_atomic_fields__
140
170
  super
141
171
  #{assignments}
142
172
  end
143
173
  RUBY
144
174
  end
145
175
 
146
- private_class_method :define_initialize_volatile_with_cas
176
+ private_class_method :define_initialize_atomic_fields
147
177
 
148
- def initialize_volatile_with_cas
178
+ def __initialize_atomic_fields__
149
179
  end
150
180
 
151
181
  end
@@ -1,6 +1,7 @@
1
1
  module Concurrent
2
2
  module Synchronization
3
3
 
4
+ # @!visibility private
4
5
  module RbxAttrVolatile
5
6
  def self.included(base)
6
7
  base.extend(ClassMethods)
@@ -0,0 +1,47 @@
1
+ module Concurrent
2
+ module Synchronization
3
+
4
+ # @!visibility private
5
+ module TruffleRubyAttrVolatile
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ def attr_volatile(*names)
12
+ names.each do |name|
13
+ ivar = :"@volatile_#{name}"
14
+
15
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
16
+ def #{name}
17
+ full_memory_barrier
18
+ #{ivar}
19
+ end
20
+
21
+ def #{name}=(value)
22
+ #{ivar} = value
23
+ full_memory_barrier
24
+ end
25
+ RUBY
26
+ end
27
+
28
+ names.map { |n| [n, :"#{n}="] }.flatten
29
+ end
30
+ end
31
+
32
+ def full_memory_barrier
33
+ TruffleRuby.full_memory_barrier
34
+ end
35
+ end
36
+
37
+ # @!visibility private
38
+ # @!macro internal_implementation_note
39
+ class TruffleRubyObject < AbstractObject
40
+ include TruffleRubyAttrVolatile
41
+
42
+ def initialize
43
+ # nothing to do
44
+ end
45
+ end
46
+ end
47
+ end
@@ -21,14 +21,16 @@ module Concurrent
21
21
  # => 2
22
22
 
23
23
  Volatile = case
24
- when Concurrent.on_cruby?
25
- MriAttrVolatile
26
- when Concurrent.on_jruby?
27
- JRubyAttrVolatile
28
- when Concurrent.on_rbx? || Concurrent.on_truffle?
29
- RbxAttrVolatile
30
- else
31
- MriAttrVolatile
32
- end
24
+ when Concurrent.on_cruby?
25
+ MriAttrVolatile
26
+ when Concurrent.on_jruby?
27
+ JRubyAttrVolatile
28
+ when Concurrent.on_rbx?
29
+ RbxAttrVolatile
30
+ when Concurrent.on_truffleruby?
31
+ TruffleRubyAttrVolatile
32
+ else
33
+ MriAttrVolatile
34
+ end
33
35
  end
34
36
  end
@@ -0,0 +1,63 @@
1
+ require 'concurrent/thread_safe/util'
2
+
3
+ # Shim for TruffleRuby.synchronized
4
+ if Concurrent.on_truffleruby? && !TruffleRuby.respond_to?(:synchronized)
5
+ module TruffleRuby
6
+ def self.synchronized(object, &block)
7
+ Truffle::System.synchronized(object, &block)
8
+ end
9
+ end
10
+ end
11
+
12
+ module Concurrent
13
+ module ThreadSafe
14
+ module Util
15
+ def self.make_synchronized_on_rbx(klass)
16
+ klass.class_eval do
17
+ private
18
+
19
+ def _mon_initialize
20
+ @_monitor = Monitor.new unless @_monitor # avoid double initialisation
21
+ end
22
+
23
+ def self.new(*args)
24
+ obj = super(*args)
25
+ obj.send(:_mon_initialize)
26
+ obj
27
+ end
28
+ end
29
+
30
+ klass.superclass.instance_methods(false).each do |method|
31
+ case method
32
+ when :new_range, :new_reserved
33
+ klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
34
+ def #{method}(*args)
35
+ obj = super
36
+ obj.send(:_mon_initialize)
37
+ obj
38
+ end
39
+ RUBY
40
+ else
41
+ klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
42
+ def #{method}(*args)
43
+ monitor = @_monitor
44
+ monitor or raise("BUG: Internal monitor was not properly initialized. Please report this to the concurrent-ruby developers.")
45
+ monitor.synchronize { super }
46
+ end
47
+ RUBY
48
+ end
49
+ end
50
+ end
51
+
52
+ def self.make_synchronized_on_truffleruby(klass)
53
+ klass.superclass.instance_methods(false).each do |method|
54
+ klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
55
+ def #{method}(*args, &block)
56
+ TruffleRuby.synchronized(self) { super(*args, &block) }
57
+ end
58
+ RUBY
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -86,15 +86,20 @@ module Concurrent
86
86
  # @!visibility private
87
87
  class Cell < Concurrent::AtomicReference
88
88
 
89
- # TODO: this only adds padding after the :value slot, need to find a way to add padding before the slot
90
- # @!visibility private
91
- attr_reader *(12.times.collect{ |i| "padding_#{i}".to_sym })
92
-
93
89
  alias_method :cas, :compare_and_set
94
90
 
95
91
  def cas_computed
96
92
  cas(current_value = value, yield(current_value))
97
93
  end
94
+
95
+ # @!visibility private
96
+ def self.padding
97
+ # TODO: this only adds padding after the :value slot, need to find a way to add padding before the slot
98
+ # TODO (pitr-ch 28-Jul-2018): the padding instance vars may not be created
99
+ # hide from yardoc in a method
100
+ attr_reader *(12.times.collect{ |i| "padding_#{i}".to_sym })
101
+ end
102
+ padding
98
103
  end
99
104
 
100
105
  extend Volatile
@@ -126,6 +126,7 @@ module Concurrent
126
126
  # task = Concurrent::TimerTask.new(execution_interval: 1, timeout_interval: 1){ 42 }
127
127
  # task.add_observer(TaskObserver.new)
128
128
  # task.execute
129
+ # sleep 4
129
130
  #
130
131
  # #=> (2013-10-13 19:08:58 -0400) Execution successfully returned 42
131
132
  # #=> (2013-10-13 19:08:59 -0400) Execution successfully returned 42
@@ -164,7 +165,7 @@ module Concurrent
164
165
 
165
166
  # Create a new TimerTask with the given task and configuration.
166
167
  #
167
- # @!macro [attach] timer_task_initialize
168
+ # @!macro timer_task_initialize
168
169
  # @param [Hash] opts the options defining task execution.
169
170
  # @option opts [Integer] :execution_interval number of seconds between
170
171
  # task executions (default: EXECUTION_INTERVAL)
@@ -189,6 +190,7 @@ module Concurrent
189
190
  def initialize(opts = {}, &task)
190
191
  raise ArgumentError.new('no block given') unless block_given?
191
192
  super
193
+ set_deref_options opts
192
194
  end
193
195
 
194
196
  # Is the executor running?
@@ -280,6 +282,7 @@ module Concurrent
280
282
  @run_now = opts[:now] || opts[:run_now]
281
283
  @executor = Concurrent::SafeTaskExecutor.new(task)
282
284
  @running = Concurrent::AtomicBoolean.new(false)
285
+ @value = nil
283
286
 
284
287
  self.observers = Collection::CopyOnNotifyObserverSet.new
285
288
  end
@@ -305,7 +308,7 @@ module Concurrent
305
308
  # @!visibility private
306
309
  def execute_task(completion)
307
310
  return nil unless @running.true?
308
- ScheduledTask.execute(execution_interval, args: [completion], &method(:timeout_task))
311
+ ScheduledTask.execute(timeout_interval, args: [completion], &method(:timeout_task))
309
312
  _success, value, reason = @executor.execute(self)
310
313
  if completion.try?
311
314
  self.value = value
@@ -24,7 +24,7 @@ module Concurrent
24
24
  attr_reader :size
25
25
 
26
26
  # @!visibility private
27
- Tuple = defined?(Rubinius::Tuple) ? Rubinius::Tuple : Array
27
+ Tuple = defined?(Rubinius::Tuple) ? Rubinius::Tuple : ::Array
28
28
  private_constant :Tuple
29
29
 
30
30
  # Create a new tuple of the given size.
@@ -8,7 +8,7 @@ module Concurrent
8
8
  #
9
9
  # @!macro thread_safe_variable_comparison
10
10
  #
11
- # {include:file:doc/tvar.md}
11
+ # {include:file:docs-source/tvar.md}
12
12
  class TVar < Synchronization::Object
13
13
  safe_initialization!
14
14
 
@@ -162,7 +162,7 @@ module Concurrent
162
162
 
163
163
  class Transaction
164
164
 
165
- ABORTED = Object.new
165
+ ABORTED = ::Object.new
166
166
 
167
167
  ReadLogEntry = Struct.new(:tvar, :version)
168
168
 
@@ -8,7 +8,7 @@ module Concurrent
8
8
  end
9
9
 
10
10
  def on_jruby_9000?
11
- on_jruby? && ruby_version(:>=, 9, 0, 0, JRUBY_VERSION)
11
+ on_jruby? && ruby_version(JRUBY_VERSION, :>=, 9, 0, 0)
12
12
  end
13
13
 
14
14
  def on_cruby?
@@ -19,8 +19,8 @@ module Concurrent
19
19
  ruby_engine == 'rbx'
20
20
  end
21
21
 
22
- def on_truffle?
23
- ruby_engine == 'jruby+truffle'
22
+ def on_truffleruby?
23
+ ruby_engine == 'truffleruby'
24
24
  end
25
25
 
26
26
  def on_windows?
@@ -39,7 +39,7 @@ module Concurrent
39
39
  defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
40
40
  end
41
41
 
42
- def ruby_version(comparison, major, minor, patch, version = RUBY_VERSION)
42
+ def ruby_version(version = RUBY_VERSION, comparison, major, minor, patch)
43
43
  result = (version.split('.').map(&:to_i) <=> [major, minor, patch])
44
44
  comparisons = { :== => [0],
45
45
  :>= => [1, 0],
@@ -42,12 +42,12 @@ module Concurrent
42
42
  GLOBAL_MONOTONIC_CLOCK = class_definition.new
43
43
  private_constant :GLOBAL_MONOTONIC_CLOCK
44
44
 
45
- # @!macro [attach] monotonic_get_time
45
+ # @!macro monotonic_get_time
46
46
  #
47
47
  # Returns the current time a tracked by the application monotonic clock.
48
48
  #
49
- # @return [Float] The current monotonic time when `since` not given else
50
- # the elapsed monotonic time between `since` and the current time
49
+ # @return [Float] The current monotonic time since some unspecified
50
+ # starting point
51
51
  #
52
52
  # @!macro monotonic_clock_warning
53
53
  def monotonic_time