concurrent-ruby 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +478 -0
  3. data/Gemfile +41 -0
  4. data/LICENSE.md +23 -0
  5. data/README.md +381 -0
  6. data/Rakefile +327 -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.rb +1 -0
  23. data/lib/concurrent.rb +134 -0
  24. data/lib/concurrent/agent.rb +587 -0
  25. data/lib/concurrent/array.rb +66 -0
  26. data/lib/concurrent/async.rb +459 -0
  27. data/lib/concurrent/atom.rb +222 -0
  28. data/lib/concurrent/atomic/abstract_thread_local_var.rb +66 -0
  29. data/lib/concurrent/atomic/atomic_boolean.rb +126 -0
  30. data/lib/concurrent/atomic/atomic_fixnum.rb +143 -0
  31. data/lib/concurrent/atomic/atomic_markable_reference.rb +164 -0
  32. data/lib/concurrent/atomic/atomic_reference.rb +204 -0
  33. data/lib/concurrent/atomic/count_down_latch.rb +100 -0
  34. data/lib/concurrent/atomic/cyclic_barrier.rb +128 -0
  35. data/lib/concurrent/atomic/event.rb +109 -0
  36. data/lib/concurrent/atomic/java_count_down_latch.rb +42 -0
  37. data/lib/concurrent/atomic/java_thread_local_var.rb +37 -0
  38. data/lib/concurrent/atomic/mutex_atomic_boolean.rb +62 -0
  39. data/lib/concurrent/atomic/mutex_atomic_fixnum.rb +75 -0
  40. data/lib/concurrent/atomic/mutex_count_down_latch.rb +44 -0
  41. data/lib/concurrent/atomic/mutex_semaphore.rb +115 -0
  42. data/lib/concurrent/atomic/read_write_lock.rb +254 -0
  43. data/lib/concurrent/atomic/reentrant_read_write_lock.rb +379 -0
  44. data/lib/concurrent/atomic/ruby_thread_local_var.rb +161 -0
  45. data/lib/concurrent/atomic/semaphore.rb +145 -0
  46. data/lib/concurrent/atomic/thread_local_var.rb +104 -0
  47. data/lib/concurrent/atomic_reference/mutex_atomic.rb +56 -0
  48. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +28 -0
  49. data/lib/concurrent/atomics.rb +10 -0
  50. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +107 -0
  51. data/lib/concurrent/collection/copy_on_write_observer_set.rb +111 -0
  52. data/lib/concurrent/collection/java_non_concurrent_priority_queue.rb +84 -0
  53. data/lib/concurrent/collection/lock_free_stack.rb +158 -0
  54. data/lib/concurrent/collection/map/atomic_reference_map_backend.rb +927 -0
  55. data/lib/concurrent/collection/map/mri_map_backend.rb +66 -0
  56. data/lib/concurrent/collection/map/non_concurrent_map_backend.rb +140 -0
  57. data/lib/concurrent/collection/map/synchronized_map_backend.rb +82 -0
  58. data/lib/concurrent/collection/non_concurrent_priority_queue.rb +143 -0
  59. data/lib/concurrent/collection/ruby_non_concurrent_priority_queue.rb +150 -0
  60. data/lib/concurrent/concern/deprecation.rb +34 -0
  61. data/lib/concurrent/concern/dereferenceable.rb +73 -0
  62. data/lib/concurrent/concern/logging.rb +32 -0
  63. data/lib/concurrent/concern/obligation.rb +220 -0
  64. data/lib/concurrent/concern/observable.rb +110 -0
  65. data/lib/concurrent/concurrent_ruby.jar +0 -0
  66. data/lib/concurrent/configuration.rb +184 -0
  67. data/lib/concurrent/constants.rb +8 -0
  68. data/lib/concurrent/dataflow.rb +81 -0
  69. data/lib/concurrent/delay.rb +199 -0
  70. data/lib/concurrent/errors.rb +69 -0
  71. data/lib/concurrent/exchanger.rb +352 -0
  72. data/lib/concurrent/executor/abstract_executor_service.rb +134 -0
  73. data/lib/concurrent/executor/cached_thread_pool.rb +62 -0
  74. data/lib/concurrent/executor/executor_service.rb +185 -0
  75. data/lib/concurrent/executor/fixed_thread_pool.rb +206 -0
  76. data/lib/concurrent/executor/immediate_executor.rb +66 -0
  77. data/lib/concurrent/executor/indirect_immediate_executor.rb +44 -0
  78. data/lib/concurrent/executor/java_executor_service.rb +91 -0
  79. data/lib/concurrent/executor/java_single_thread_executor.rb +29 -0
  80. data/lib/concurrent/executor/java_thread_pool_executor.rb +123 -0
  81. data/lib/concurrent/executor/ruby_executor_service.rb +78 -0
  82. data/lib/concurrent/executor/ruby_single_thread_executor.rb +22 -0
  83. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +362 -0
  84. data/lib/concurrent/executor/safe_task_executor.rb +35 -0
  85. data/lib/concurrent/executor/serial_executor_service.rb +34 -0
  86. data/lib/concurrent/executor/serialized_execution.rb +107 -0
  87. data/lib/concurrent/executor/serialized_execution_delegator.rb +28 -0
  88. data/lib/concurrent/executor/simple_executor_service.rb +100 -0
  89. data/lib/concurrent/executor/single_thread_executor.rb +56 -0
  90. data/lib/concurrent/executor/thread_pool_executor.rb +87 -0
  91. data/lib/concurrent/executor/timer_set.rb +173 -0
  92. data/lib/concurrent/executors.rb +20 -0
  93. data/lib/concurrent/future.rb +141 -0
  94. data/lib/concurrent/hash.rb +59 -0
  95. data/lib/concurrent/immutable_struct.rb +93 -0
  96. data/lib/concurrent/ivar.rb +207 -0
  97. data/lib/concurrent/map.rb +337 -0
  98. data/lib/concurrent/maybe.rb +229 -0
  99. data/lib/concurrent/mutable_struct.rb +229 -0
  100. data/lib/concurrent/mvar.rb +242 -0
  101. data/lib/concurrent/options.rb +42 -0
  102. data/lib/concurrent/promise.rb +579 -0
  103. data/lib/concurrent/promises.rb +2167 -0
  104. data/lib/concurrent/re_include.rb +58 -0
  105. data/lib/concurrent/scheduled_task.rb +318 -0
  106. data/lib/concurrent/set.rb +66 -0
  107. data/lib/concurrent/settable_struct.rb +129 -0
  108. data/lib/concurrent/synchronization.rb +30 -0
  109. data/lib/concurrent/synchronization/abstract_lockable_object.rb +98 -0
  110. data/lib/concurrent/synchronization/abstract_object.rb +24 -0
  111. data/lib/concurrent/synchronization/abstract_struct.rb +160 -0
  112. data/lib/concurrent/synchronization/condition.rb +60 -0
  113. data/lib/concurrent/synchronization/jruby_lockable_object.rb +13 -0
  114. data/lib/concurrent/synchronization/jruby_object.rb +45 -0
  115. data/lib/concurrent/synchronization/lock.rb +36 -0
  116. data/lib/concurrent/synchronization/lockable_object.rb +74 -0
  117. data/lib/concurrent/synchronization/mri_object.rb +44 -0
  118. data/lib/concurrent/synchronization/mutex_lockable_object.rb +76 -0
  119. data/lib/concurrent/synchronization/object.rb +183 -0
  120. data/lib/concurrent/synchronization/rbx_lockable_object.rb +65 -0
  121. data/lib/concurrent/synchronization/rbx_object.rb +49 -0
  122. data/lib/concurrent/synchronization/truffleruby_object.rb +47 -0
  123. data/lib/concurrent/synchronization/volatile.rb +36 -0
  124. data/lib/concurrent/thread_safe/synchronized_delegator.rb +50 -0
  125. data/lib/concurrent/thread_safe/util.rb +16 -0
  126. data/lib/concurrent/thread_safe/util/adder.rb +74 -0
  127. data/lib/concurrent/thread_safe/util/cheap_lockable.rb +118 -0
  128. data/lib/concurrent/thread_safe/util/data_structures.rb +63 -0
  129. data/lib/concurrent/thread_safe/util/power_of_two_tuple.rb +38 -0
  130. data/lib/concurrent/thread_safe/util/striped64.rb +246 -0
  131. data/lib/concurrent/thread_safe/util/volatile.rb +75 -0
  132. data/lib/concurrent/thread_safe/util/xor_shift_random.rb +50 -0
  133. data/lib/concurrent/timer_task.rb +334 -0
  134. data/lib/concurrent/tuple.rb +86 -0
  135. data/lib/concurrent/tvar.rb +258 -0
  136. data/lib/concurrent/utility/at_exit.rb +97 -0
  137. data/lib/concurrent/utility/engine.rb +56 -0
  138. data/lib/concurrent/utility/monotonic_time.rb +58 -0
  139. data/lib/concurrent/utility/native_extension_loader.rb +79 -0
  140. data/lib/concurrent/utility/native_integer.rb +53 -0
  141. data/lib/concurrent/utility/processor_counter.rb +158 -0
  142. data/lib/concurrent/version.rb +3 -0
  143. metadata +193 -0
@@ -0,0 +1,164 @@
1
+ module Concurrent
2
+ # An atomic reference which maintains an object reference along with a mark bit
3
+ # that can be updated atomically.
4
+ #
5
+ # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicMarkableReference.html
6
+ # java.util.concurrent.atomic.AtomicMarkableReference
7
+ class AtomicMarkableReference < ::Concurrent::Synchronization::Object
8
+
9
+ attr_atomic(:reference)
10
+ private :reference, :reference=, :swap_reference, :compare_and_set_reference, :update_reference
11
+
12
+ def initialize(value = nil, mark = false)
13
+ super()
14
+ self.reference = immutable_array(value, mark)
15
+ end
16
+
17
+ # Atomically sets the value and mark to the given updated value and
18
+ # mark given both:
19
+ # - the current value == the expected value &&
20
+ # - the current mark == the expected mark
21
+ #
22
+ # @param [Object] expected_val the expected value
23
+ # @param [Object] new_val the new value
24
+ # @param [Boolean] expected_mark the expected mark
25
+ # @param [Boolean] new_mark the new mark
26
+ #
27
+ # @return [Boolean] `true` if successful. A `false` return indicates
28
+ # that the actual value was not equal to the expected value or the
29
+ # actual mark was not equal to the expected mark
30
+ def compare_and_set(expected_val, new_val, expected_mark, new_mark)
31
+ # Memoize a valid reference to the current AtomicReference for
32
+ # later comparison.
33
+ current = reference
34
+ curr_val, curr_mark = current
35
+
36
+ # Ensure that that the expected marks match.
37
+ return false unless expected_mark == curr_mark
38
+
39
+ if expected_val.is_a? Numeric
40
+ # If the object is a numeric, we need to ensure we are comparing
41
+ # the numerical values
42
+ return false unless expected_val == curr_val
43
+ else
44
+ # Otherwise, we need to ensure we are comparing the object identity.
45
+ # Theoretically, this could be incorrect if a user monkey-patched
46
+ # `Object#equal?`, but they should know that they are playing with
47
+ # fire at that point.
48
+ return false unless expected_val.equal? curr_val
49
+ end
50
+
51
+ prospect = immutable_array(new_val, new_mark)
52
+
53
+ compare_and_set_reference current, prospect
54
+ end
55
+
56
+ alias_method :compare_and_swap, :compare_and_set
57
+
58
+ # Gets the current reference and marked values.
59
+ #
60
+ # @return [Array] the current reference and marked values
61
+ def get
62
+ reference
63
+ end
64
+
65
+ # Gets the current value of the reference
66
+ #
67
+ # @return [Object] the current value of the reference
68
+ def value
69
+ reference[0]
70
+ end
71
+
72
+ # Gets the current marked value
73
+ #
74
+ # @return [Boolean] the current marked value
75
+ def mark
76
+ reference[1]
77
+ end
78
+
79
+ alias_method :marked?, :mark
80
+
81
+ # _Unconditionally_ sets to the given value of both the reference and
82
+ # the mark.
83
+ #
84
+ # @param [Object] new_val the new value
85
+ # @param [Boolean] new_mark the new mark
86
+ #
87
+ # @return [Array] both the new value and the new mark
88
+ def set(new_val, new_mark)
89
+ self.reference = immutable_array(new_val, new_mark)
90
+ end
91
+
92
+ # Pass the current value and marked state to the given block, replacing it
93
+ # with the block's results. May retry if the value changes during the
94
+ # block's execution.
95
+ #
96
+ # @yield [Object] Calculate a new value and marked state for the atomic
97
+ # reference using given (old) value and (old) marked
98
+ # @yieldparam [Object] old_val the starting value of the atomic reference
99
+ # @yieldparam [Boolean] old_mark the starting state of marked
100
+ #
101
+ # @return [Array] the new value and new mark
102
+ def update
103
+ loop do
104
+ old_val, old_mark = reference
105
+ new_val, new_mark = yield old_val, old_mark
106
+
107
+ if compare_and_set old_val, new_val, old_mark, new_mark
108
+ return immutable_array(new_val, new_mark)
109
+ end
110
+ end
111
+ end
112
+
113
+ # Pass the current value to the given block, replacing it
114
+ # with the block's result. Raise an exception if the update
115
+ # fails.
116
+ #
117
+ # @yield [Object] Calculate a new value and marked state for the atomic
118
+ # reference using given (old) value and (old) marked
119
+ # @yieldparam [Object] old_val the starting value of the atomic reference
120
+ # @yieldparam [Boolean] old_mark the starting state of marked
121
+ #
122
+ # @return [Array] the new value and marked state
123
+ #
124
+ # @raise [Concurrent::ConcurrentUpdateError] if the update fails
125
+ def try_update!
126
+ old_val, old_mark = reference
127
+ new_val, new_mark = yield old_val, old_mark
128
+
129
+ unless compare_and_set old_val, new_val, old_mark, new_mark
130
+ fail ::Concurrent::ConcurrentUpdateError,
131
+ 'AtomicMarkableReference: Update failed due to race condition.',
132
+ 'Note: If you would like to guarantee an update, please use ' +
133
+ 'the `AtomicMarkableReference#update` method.'
134
+ end
135
+
136
+ immutable_array(new_val, new_mark)
137
+ end
138
+
139
+ # Pass the current value to the given block, replacing it with the
140
+ # block's result. Simply return nil if update fails.
141
+ #
142
+ # @yield [Object] Calculate a new value and marked state for the atomic
143
+ # reference using given (old) value and (old) marked
144
+ # @yieldparam [Object] old_val the starting value of the atomic reference
145
+ # @yieldparam [Boolean] old_mark the starting state of marked
146
+ #
147
+ # @return [Array] the new value and marked state, or nil if
148
+ # the update failed
149
+ def try_update
150
+ old_val, old_mark = reference
151
+ new_val, new_mark = yield old_val, old_mark
152
+
153
+ return unless compare_and_set old_val, new_val, old_mark, new_mark
154
+
155
+ immutable_array(new_val, new_mark)
156
+ end
157
+
158
+ private
159
+
160
+ def immutable_array(*args)
161
+ args.freeze
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,204 @@
1
+ require 'concurrent/synchronization'
2
+ require 'concurrent/utility/engine'
3
+ require 'concurrent/atomic_reference/numeric_cas_wrapper'
4
+
5
+ # Shim for TruffleRuby::AtomicReference
6
+ if Concurrent.on_truffleruby? && !defined?(TruffleRuby::AtomicReference)
7
+ # @!visibility private
8
+ module TruffleRuby
9
+ AtomicReference = Truffle::AtomicReference
10
+ end
11
+ end
12
+
13
+ module Concurrent
14
+
15
+ # Define update methods that use direct paths
16
+ #
17
+ # @!visibility private
18
+ # @!macro internal_implementation_note
19
+ module AtomicDirectUpdate
20
+
21
+ # @!macro atomic_reference_method_update
22
+ #
23
+ # Pass the current value to the given block, replacing it
24
+ # with the block's result. May retry if the value changes
25
+ # during the block's execution.
26
+ #
27
+ # @yield [Object] Calculate a new value for the atomic reference using
28
+ # given (old) value
29
+ # @yieldparam [Object] old_value the starting value of the atomic reference
30
+ # @return [Object] the new value
31
+ def update
32
+ true until compare_and_set(old_value = get, new_value = yield(old_value))
33
+ new_value
34
+ end
35
+
36
+ # @!macro atomic_reference_method_try_update
37
+ #
38
+ # Pass the current value to the given block, replacing it
39
+ # with the block's result. Return nil if the update fails.
40
+ #
41
+ # @yield [Object] Calculate a new value for the atomic reference using
42
+ # given (old) value
43
+ # @yieldparam [Object] old_value the starting value of the atomic reference
44
+ # @note This method was altered to avoid raising an exception by default.
45
+ # Instead, this method now returns `nil` in case of failure. For more info,
46
+ # please see: https://github.com/ruby-concurrency/concurrent-ruby/pull/336
47
+ # @return [Object] the new value, or nil if update failed
48
+ def try_update
49
+ old_value = get
50
+ new_value = yield old_value
51
+
52
+ return unless compare_and_set old_value, new_value
53
+
54
+ new_value
55
+ end
56
+
57
+ # @!macro atomic_reference_method_try_update!
58
+ #
59
+ # Pass the current value to the given block, replacing it
60
+ # with the block's result. Raise an exception if the update
61
+ # fails.
62
+ #
63
+ # @yield [Object] Calculate a new value for the atomic reference using
64
+ # given (old) value
65
+ # @yieldparam [Object] old_value the starting value of the atomic reference
66
+ # @note This behavior mimics the behavior of the original
67
+ # `AtomicReference#try_update` API. The reason this was changed was to
68
+ # avoid raising exceptions (which are inherently slow) by default. For more
69
+ # info: https://github.com/ruby-concurrency/concurrent-ruby/pull/336
70
+ # @return [Object] the new value
71
+ # @raise [Concurrent::ConcurrentUpdateError] if the update fails
72
+ def try_update!
73
+ old_value = get
74
+ new_value = yield old_value
75
+ unless compare_and_set(old_value, new_value)
76
+ if $VERBOSE
77
+ raise ConcurrentUpdateError, "Update failed"
78
+ else
79
+ raise ConcurrentUpdateError, "Update failed", ConcurrentUpdateError::CONC_UP_ERR_BACKTRACE
80
+ end
81
+ end
82
+ new_value
83
+ end
84
+ end
85
+
86
+ require 'concurrent/atomic_reference/mutex_atomic'
87
+
88
+ # @!macro atomic_reference
89
+ #
90
+ # An object reference that may be updated atomically. All read and write
91
+ # operations have java volatile semantic.
92
+ #
93
+ # @!macro thread_safe_variable_comparison
94
+ #
95
+ # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html
96
+ # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html
97
+ #
98
+ # @!method initialize(value = nil)
99
+ # @!macro atomic_reference_method_initialize
100
+ # @param [Object] value The initial value.
101
+ #
102
+ # @!method get
103
+ # @!macro atomic_reference_method_get
104
+ # Gets the current value.
105
+ # @return [Object] the current value
106
+ #
107
+ # @!method set(new_value)
108
+ # @!macro atomic_reference_method_set
109
+ # Sets to the given value.
110
+ # @param [Object] new_value the new value
111
+ # @return [Object] the new value
112
+ #
113
+ # @!method get_and_set(new_value)
114
+ # @!macro atomic_reference_method_get_and_set
115
+ # Atomically sets to the given value and returns the old value.
116
+ # @param [Object] new_value the new value
117
+ # @return [Object] the old value
118
+ #
119
+ # @!method compare_and_set(old_value, new_value)
120
+ # @!macro atomic_reference_method_compare_and_set
121
+ #
122
+ # Atomically sets the value to the given updated value if
123
+ # the current value == the expected value.
124
+ #
125
+ # @param [Object] old_value the expected value
126
+ # @param [Object] new_value the new value
127
+ #
128
+ # @return [Boolean] `true` if successful. A `false` return indicates
129
+ # that the actual value was not equal to the expected value.
130
+ #
131
+ # @!method update
132
+ # @!macro atomic_reference_method_update
133
+ #
134
+ # @!method try_update
135
+ # @!macro atomic_reference_method_try_update
136
+ #
137
+ # @!method try_update!
138
+ # @!macro atomic_reference_method_try_update!
139
+
140
+
141
+ # @!macro internal_implementation_note
142
+ class ConcurrentUpdateError < ThreadError
143
+ # frozen pre-allocated backtrace to speed ConcurrentUpdateError
144
+ CONC_UP_ERR_BACKTRACE = ['backtrace elided; set verbose to enable'].freeze
145
+ end
146
+
147
+ # @!macro internal_implementation_note
148
+ AtomicReferenceImplementation = case
149
+ when Concurrent.on_cruby? && Concurrent.c_extensions_loaded?
150
+ # @!visibility private
151
+ # @!macro internal_implementation_note
152
+ class CAtomicReference
153
+ include AtomicDirectUpdate
154
+ include AtomicNumericCompareAndSetWrapper
155
+ alias_method :compare_and_swap, :compare_and_set
156
+ end
157
+ CAtomicReference
158
+ when Concurrent.on_jruby?
159
+ # @!visibility private
160
+ # @!macro internal_implementation_note
161
+ class JavaAtomicReference
162
+ include AtomicDirectUpdate
163
+ end
164
+ JavaAtomicReference
165
+ when Concurrent.on_truffleruby?
166
+ class TruffleRubyAtomicReference < TruffleRuby::AtomicReference
167
+ include AtomicDirectUpdate
168
+ alias_method :value, :get
169
+ alias_method :value=, :set
170
+ alias_method :compare_and_swap, :compare_and_set
171
+ alias_method :swap, :get_and_set
172
+ end
173
+ when Concurrent.on_rbx?
174
+ # @note Extends `Rubinius::AtomicReference` version adding aliases
175
+ # and numeric logic.
176
+ #
177
+ # @!visibility private
178
+ # @!macro internal_implementation_note
179
+ class RbxAtomicReference < Rubinius::AtomicReference
180
+ alias_method :_compare_and_set, :compare_and_set
181
+ include AtomicDirectUpdate
182
+ include AtomicNumericCompareAndSetWrapper
183
+ alias_method :value, :get
184
+ alias_method :value=, :set
185
+ alias_method :swap, :get_and_set
186
+ alias_method :compare_and_swap, :compare_and_set
187
+ end
188
+ RbxAtomicReference
189
+ else
190
+ MutexAtomicReference
191
+ end
192
+ private_constant :AtomicReferenceImplementation
193
+
194
+ # @!macro atomic_reference
195
+ class AtomicReference < AtomicReferenceImplementation
196
+
197
+ # @return [String] Short string representation.
198
+ def to_s
199
+ format '%s value:%s>', super[0..-2], get
200
+ end
201
+
202
+ alias_method :inspect, :to_s
203
+ end
204
+ end
@@ -0,0 +1,100 @@
1
+ require 'concurrent/atomic/mutex_count_down_latch'
2
+ require 'concurrent/atomic/java_count_down_latch'
3
+ require 'concurrent/utility/engine'
4
+
5
+ module Concurrent
6
+
7
+ ###################################################################
8
+
9
+ # @!macro count_down_latch_method_initialize
10
+ #
11
+ # Create a new `CountDownLatch` with the initial `count`.
12
+ #
13
+ # @param [new] count the initial count
14
+ #
15
+ # @raise [ArgumentError] if `count` is not an integer or is less than zero
16
+
17
+ # @!macro count_down_latch_method_wait
18
+ #
19
+ # Block on the latch until the counter reaches zero or until `timeout` is reached.
20
+ #
21
+ # @param [Fixnum] timeout the number of seconds to wait for the counter or `nil`
22
+ # to block indefinitely
23
+ # @return [Boolean] `true` if the `count` reaches zero else false on `timeout`
24
+
25
+ # @!macro count_down_latch_method_count_down
26
+ #
27
+ # Signal the latch to decrement the counter. Will signal all blocked threads when
28
+ # the `count` reaches zero.
29
+
30
+ # @!macro count_down_latch_method_count
31
+ #
32
+ # The current value of the counter.
33
+ #
34
+ # @return [Fixnum] the current value of the counter
35
+
36
+ ###################################################################
37
+
38
+ # @!macro count_down_latch_public_api
39
+ #
40
+ # @!method initialize(count = 1)
41
+ # @!macro count_down_latch_method_initialize
42
+ #
43
+ # @!method wait(timeout = nil)
44
+ # @!macro count_down_latch_method_wait
45
+ #
46
+ # @!method count_down
47
+ # @!macro count_down_latch_method_count_down
48
+ #
49
+ # @!method count
50
+ # @!macro count_down_latch_method_count
51
+
52
+ ###################################################################
53
+
54
+ # @!visibility private
55
+ # @!macro internal_implementation_note
56
+ CountDownLatchImplementation = case
57
+ when Concurrent.on_jruby?
58
+ JavaCountDownLatch
59
+ else
60
+ MutexCountDownLatch
61
+ end
62
+ private_constant :CountDownLatchImplementation
63
+
64
+ # @!macro count_down_latch
65
+ #
66
+ # A synchronization object that allows one thread to wait on multiple other threads.
67
+ # The thread that will wait creates a `CountDownLatch` and sets the initial value
68
+ # (normally equal to the number of other threads). The initiating thread passes the
69
+ # latch to the other threads then waits for the other threads by calling the `#wait`
70
+ # method. Each of the other threads calls `#count_down` when done with its work.
71
+ # When the latch counter reaches zero the waiting thread is unblocked and continues
72
+ # with its work. A `CountDownLatch` can be used only once. Its value cannot be reset.
73
+ #
74
+ # @!macro count_down_latch_public_api
75
+ # @example Waiter and Decrementer
76
+ # latch = Concurrent::CountDownLatch.new(3)
77
+ #
78
+ # waiter = Thread.new do
79
+ # latch.wait()
80
+ # puts ("Waiter released")
81
+ # end
82
+ #
83
+ # decrementer = Thread.new do
84
+ # sleep(1)
85
+ # latch.count_down
86
+ # puts latch.count
87
+ #
88
+ # sleep(1)
89
+ # latch.count_down
90
+ # puts latch.count
91
+ #
92
+ # sleep(1)
93
+ # latch.count_down
94
+ # puts latch.count
95
+ # end
96
+ #
97
+ # [waiter, decrementer].each(&:join)
98
+ class CountDownLatch < CountDownLatchImplementation
99
+ end
100
+ end