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,222 @@
1
+ require 'concurrent/atomic/atomic_reference'
2
+ require 'concurrent/collection/copy_on_notify_observer_set'
3
+ require 'concurrent/concern/observable'
4
+ require 'concurrent/synchronization'
5
+
6
+ # @!macro thread_safe_variable_comparison
7
+ #
8
+ # ## Thread-safe Variable Classes
9
+ #
10
+ # Each of the thread-safe variable classes is designed to solve a different
11
+ # problem. In general:
12
+ #
13
+ # * *{Concurrent::Agent}:* Shared, mutable variable providing independent,
14
+ # uncoordinated, *asynchronous* change of individual values. Best used when
15
+ # the value will undergo frequent, complex updates. Suitable when the result
16
+ # of an update does not need to be known immediately.
17
+ # * *{Concurrent::Atom}:* Shared, mutable variable providing independent,
18
+ # uncoordinated, *synchronous* change of individual values. Best used when
19
+ # the value will undergo frequent reads but only occasional, though complex,
20
+ # updates. Suitable when the result of an update must be known immediately.
21
+ # * *{Concurrent::AtomicReference}:* A simple object reference that can be
22
+ # atomically. Updates are synchronous but fast. Best used when updates a
23
+ # simple set operations. Not suitable when updates are complex.
24
+ # {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar
25
+ # but optimized for the given data type.
26
+ # * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used
27
+ # when two or more threads need to exchange data. The threads will pair then
28
+ # block on each other until the exchange is complete.
29
+ # * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread
30
+ # must give a value to another, which must take the value. The threads will
31
+ # block on each other until the exchange is complete.
32
+ # * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which
33
+ # holds a different value for each thread which has access. Often used as
34
+ # an instance variable in objects which must maintain different state
35
+ # for different threads.
36
+ # * *{Concurrent::TVar}:* Shared, mutable variables which provide
37
+ # *coordinated*, *synchronous*, change of *many* stated. Used when multiple
38
+ # value must change together, in an all-or-nothing transaction.
39
+
40
+
41
+ module Concurrent
42
+
43
+ # Atoms provide a way to manage shared, synchronous, independent state.
44
+ #
45
+ # An atom is initialized with an initial value and an optional validation
46
+ # proc. At any time the value of the atom can be synchronously and safely
47
+ # changed. If a validator is given at construction then any new value
48
+ # will be checked against the validator and will be rejected if the
49
+ # validator returns false or raises an exception.
50
+ #
51
+ # There are two ways to change the value of an atom: {#compare_and_set} and
52
+ # {#swap}. The former will set the new value if and only if it validates and
53
+ # the current value matches the new value. The latter will atomically set the
54
+ # new value to the result of running the given block if and only if that
55
+ # value validates.
56
+ #
57
+ # ## Example
58
+ #
59
+ # ```
60
+ # def next_fibonacci(set = nil)
61
+ # return [0, 1] if set.nil?
62
+ # set + [set[-2..-1].reduce{|sum,x| sum + x }]
63
+ # end
64
+ #
65
+ # # create an atom with an initial value
66
+ # atom = Concurrent::Atom.new(next_fibonacci)
67
+ #
68
+ # # send a few update requests
69
+ # 5.times do
70
+ # atom.swap{|set| next_fibonacci(set) }
71
+ # end
72
+ #
73
+ # # get the current value
74
+ # atom.value #=> [0, 1, 1, 2, 3, 5, 8]
75
+ # ```
76
+ #
77
+ # ## Observation
78
+ #
79
+ # Atoms support observers through the {Concurrent::Observable} mixin module.
80
+ # Notification of observers occurs every time the value of the Atom changes.
81
+ # When notified the observer will receive three arguments: `time`, `old_value`,
82
+ # and `new_value`. The `time` argument is the time at which the value change
83
+ # occurred. The `old_value` is the value of the Atom when the change began
84
+ # The `new_value` is the value to which the Atom was set when the change
85
+ # completed. Note that `old_value` and `new_value` may be the same. This is
86
+ # not an error. It simply means that the change operation returned the same
87
+ # value.
88
+ #
89
+ # Unlike in Clojure, `Atom` cannot participate in {Concurrent::TVar} transactions.
90
+ #
91
+ # @!macro thread_safe_variable_comparison
92
+ #
93
+ # @see http://clojure.org/atoms Clojure Atoms
94
+ # @see http://clojure.org/state Values and Change - Clojure's approach to Identity and State
95
+ class Atom < Synchronization::Object
96
+ include Concern::Observable
97
+
98
+ safe_initialization!
99
+ attr_atomic(:value)
100
+ private :value=, :swap_value, :compare_and_set_value, :update_value
101
+ public :value
102
+ alias_method :deref, :value
103
+
104
+ # @!method value
105
+ # The current value of the atom.
106
+ #
107
+ # @return [Object] The current value.
108
+
109
+ # Create a new atom with the given initial value.
110
+ #
111
+ # @param [Object] value The initial value
112
+ # @param [Hash] opts The options used to configure the atom
113
+ # @option opts [Proc] :validator (nil) Optional proc used to validate new
114
+ # values. It must accept one and only one argument which will be the
115
+ # intended new value. The validator will return true if the new value
116
+ # is acceptable else return false (preferrably) or raise an exception.
117
+ #
118
+ # @!macro deref_options
119
+ #
120
+ # @raise [ArgumentError] if the validator is not a `Proc` (when given)
121
+ def initialize(value, opts = {})
122
+ super()
123
+ @Validator = opts.fetch(:validator, -> v { true })
124
+ self.observers = Collection::CopyOnNotifyObserverSet.new
125
+ self.value = value
126
+ end
127
+
128
+ # Atomically swaps the value of atom using the given block. The current
129
+ # value will be passed to the block, as will any arguments passed as
130
+ # arguments to the function. The new value will be validated against the
131
+ # (optional) validator proc given at construction. If validation fails the
132
+ # value will not be changed.
133
+ #
134
+ # Internally, {#swap} reads the current value, applies the block to it, and
135
+ # attempts to compare-and-set it in. Since another thread may have changed
136
+ # the value in the intervening time, it may have to retry, and does so in a
137
+ # spin loop. The net effect is that the value will always be the result of
138
+ # the application of the supplied block to a current value, atomically.
139
+ # However, because the block might be called multiple times, it must be free
140
+ # of side effects.
141
+ #
142
+ # @note The given block may be called multiple times, and thus should be free
143
+ # of side effects.
144
+ #
145
+ # @param [Object] args Zero or more arguments passed to the block.
146
+ #
147
+ # @yield [value, args] Calculates a new value for the atom based on the
148
+ # current value and any supplied arguments.
149
+ # @yieldparam value [Object] The current value of the atom.
150
+ # @yieldparam args [Object] All arguments passed to the function, in order.
151
+ # @yieldreturn [Object] The intended new value of the atom.
152
+ #
153
+ # @return [Object] The final value of the atom after all operations and
154
+ # validations are complete.
155
+ #
156
+ # @raise [ArgumentError] When no block is given.
157
+ def swap(*args)
158
+ raise ArgumentError.new('no block given') unless block_given?
159
+
160
+ loop do
161
+ old_value = value
162
+ new_value = yield(old_value, *args)
163
+ begin
164
+ break old_value unless valid?(new_value)
165
+ break new_value if compare_and_set(old_value, new_value)
166
+ rescue
167
+ break old_value
168
+ end
169
+ end
170
+ end
171
+
172
+ # Atomically sets the value of atom to the new value if and only if the
173
+ # current value of the atom is identical to the old value and the new
174
+ # value successfully validates against the (optional) validator given
175
+ # at construction.
176
+ #
177
+ # @param [Object] old_value The expected current value.
178
+ # @param [Object] new_value The intended new value.
179
+ #
180
+ # @return [Boolean] True if the value is changed else false.
181
+ def compare_and_set(old_value, new_value)
182
+ if valid?(new_value) && compare_and_set_value(old_value, new_value)
183
+ observers.notify_observers(Time.now, old_value, new_value)
184
+ true
185
+ else
186
+ false
187
+ end
188
+ end
189
+
190
+ # Atomically sets the value of atom to the new value without regard for the
191
+ # current value so long as the new value successfully validates against the
192
+ # (optional) validator given at construction.
193
+ #
194
+ # @param [Object] new_value The intended new value.
195
+ #
196
+ # @return [Object] The final value of the atom after all operations and
197
+ # validations are complete.
198
+ def reset(new_value)
199
+ old_value = value
200
+ if valid?(new_value)
201
+ self.value = new_value
202
+ observers.notify_observers(Time.now, old_value, new_value)
203
+ new_value
204
+ else
205
+ old_value
206
+ end
207
+ end
208
+
209
+ private
210
+
211
+ # Is the new value valid?
212
+ #
213
+ # @param [Object] new_value The intended new value.
214
+ # @return [Boolean] false if the validator function returns false or raises
215
+ # an exception else true
216
+ def valid?(new_value)
217
+ @Validator.call(new_value)
218
+ rescue
219
+ false
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,66 @@
1
+ require 'concurrent/constants'
2
+
3
+ module Concurrent
4
+
5
+ # @!macro thread_local_var
6
+ # @!macro internal_implementation_note
7
+ # @!visibility private
8
+ class AbstractThreadLocalVar
9
+
10
+ # @!macro thread_local_var_method_initialize
11
+ def initialize(default = nil, &default_block)
12
+ if default && block_given?
13
+ raise ArgumentError, "Cannot use both value and block as default value"
14
+ end
15
+
16
+ if block_given?
17
+ @default_block = default_block
18
+ @default = nil
19
+ else
20
+ @default_block = nil
21
+ @default = default
22
+ end
23
+
24
+ allocate_storage
25
+ end
26
+
27
+ # @!macro thread_local_var_method_get
28
+ def value
29
+ raise NotImplementedError
30
+ end
31
+
32
+ # @!macro thread_local_var_method_set
33
+ def value=(value)
34
+ raise NotImplementedError
35
+ end
36
+
37
+ # @!macro thread_local_var_method_bind
38
+ def bind(value, &block)
39
+ if block_given?
40
+ old_value = self.value
41
+ begin
42
+ self.value = value
43
+ yield
44
+ ensure
45
+ self.value = old_value
46
+ end
47
+ end
48
+ end
49
+
50
+ protected
51
+
52
+ # @!visibility private
53
+ def allocate_storage
54
+ raise NotImplementedError
55
+ end
56
+
57
+ # @!visibility private
58
+ def default
59
+ if @default_block
60
+ self.value = @default_block.call
61
+ else
62
+ @default
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,126 @@
1
+ require 'concurrent/atomic/mutex_atomic_boolean'
2
+ require 'concurrent/synchronization'
3
+
4
+ module Concurrent
5
+
6
+ ###################################################################
7
+
8
+ # @!macro atomic_boolean_method_initialize
9
+ #
10
+ # Creates a new `AtomicBoolean` with the given initial value.
11
+ #
12
+ # @param [Boolean] initial the initial value
13
+
14
+ # @!macro atomic_boolean_method_value_get
15
+ #
16
+ # Retrieves the current `Boolean` value.
17
+ #
18
+ # @return [Boolean] the current value
19
+
20
+ # @!macro atomic_boolean_method_value_set
21
+ #
22
+ # Explicitly sets the value.
23
+ #
24
+ # @param [Boolean] value the new value to be set
25
+ #
26
+ # @return [Boolean] the current value
27
+
28
+ # @!macro atomic_boolean_method_true_question
29
+ #
30
+ # Is the current value `true`
31
+ #
32
+ # @return [Boolean] true if the current value is `true`, else false
33
+
34
+ # @!macro atomic_boolean_method_false_question
35
+ #
36
+ # Is the current value `false`
37
+ #
38
+ # @return [Boolean] true if the current value is `false`, else false
39
+
40
+ # @!macro atomic_boolean_method_make_true
41
+ #
42
+ # Explicitly sets the value to true.
43
+ #
44
+ # @return [Boolean] true is value has changed, otherwise false
45
+
46
+ # @!macro atomic_boolean_method_make_false
47
+ #
48
+ # Explicitly sets the value to false.
49
+ #
50
+ # @return [Boolean] true is value has changed, otherwise false
51
+
52
+ ###################################################################
53
+
54
+ # @!macro atomic_boolean_public_api
55
+ #
56
+ # @!method initialize(initial = false)
57
+ # @!macro atomic_boolean_method_initialize
58
+ #
59
+ # @!method value
60
+ # @!macro atomic_boolean_method_value_get
61
+ #
62
+ # @!method value=(value)
63
+ # @!macro atomic_boolean_method_value_set
64
+ #
65
+ # @!method true?
66
+ # @!macro atomic_boolean_method_true_question
67
+ #
68
+ # @!method false?
69
+ # @!macro atomic_boolean_method_false_question
70
+ #
71
+ # @!method make_true
72
+ # @!macro atomic_boolean_method_make_true
73
+ #
74
+ # @!method make_false
75
+ # @!macro atomic_boolean_method_make_false
76
+
77
+ ###################################################################
78
+
79
+ # @!visibility private
80
+ # @!macro internal_implementation_note
81
+ AtomicBooleanImplementation = case
82
+ when defined?(JavaAtomicBoolean)
83
+ JavaAtomicBoolean
84
+ when defined?(CAtomicBoolean)
85
+ CAtomicBoolean
86
+ else
87
+ MutexAtomicBoolean
88
+ end
89
+ private_constant :AtomicBooleanImplementation
90
+
91
+ # @!macro atomic_boolean
92
+ #
93
+ # A boolean value that can be updated atomically. Reads and writes to an atomic
94
+ # boolean and thread-safe and guaranteed to succeed. Reads and writes may block
95
+ # briefly but no explicit locking is required.
96
+ #
97
+ # @!macro thread_safe_variable_comparison
98
+ #
99
+ # Performance:
100
+ #
101
+ # ```
102
+ # Testing with ruby 2.1.2
103
+ # Testing with Concurrent::MutexAtomicBoolean...
104
+ # 2.790000 0.000000 2.790000 ( 2.791454)
105
+ # Testing with Concurrent::CAtomicBoolean...
106
+ # 0.740000 0.000000 0.740000 ( 0.740206)
107
+ #
108
+ # Testing with jruby 1.9.3
109
+ # Testing with Concurrent::MutexAtomicBoolean...
110
+ # 5.240000 2.520000 7.760000 ( 3.683000)
111
+ # Testing with Concurrent::JavaAtomicBoolean...
112
+ # 3.340000 0.010000 3.350000 ( 0.855000)
113
+ # ```
114
+ #
115
+ # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html java.util.concurrent.atomic.AtomicBoolean
116
+ #
117
+ # @!macro atomic_boolean_public_api
118
+ class AtomicBoolean < AtomicBooleanImplementation
119
+ # @return [String] Short string representation.
120
+ def to_s
121
+ format '%s value:%s>', super[0..-2], value
122
+ end
123
+
124
+ alias_method :inspect, :to_s
125
+ end
126
+ end
@@ -0,0 +1,143 @@
1
+ require 'concurrent/atomic/mutex_atomic_fixnum'
2
+ require 'concurrent/synchronization'
3
+
4
+ module Concurrent
5
+
6
+ ###################################################################
7
+
8
+ # @!macro atomic_fixnum_method_initialize
9
+ #
10
+ # Creates a new `AtomicFixnum` with the given initial value.
11
+ #
12
+ # @param [Fixnum] initial the initial value
13
+ # @raise [ArgumentError] if the initial value is not a `Fixnum`
14
+
15
+ # @!macro atomic_fixnum_method_value_get
16
+ #
17
+ # Retrieves the current `Fixnum` value.
18
+ #
19
+ # @return [Fixnum] the current value
20
+
21
+ # @!macro atomic_fixnum_method_value_set
22
+ #
23
+ # Explicitly sets the value.
24
+ #
25
+ # @param [Fixnum] value the new value to be set
26
+ #
27
+ # @return [Fixnum] the current value
28
+ #
29
+ # @raise [ArgumentError] if the new value is not a `Fixnum`
30
+
31
+ # @!macro atomic_fixnum_method_increment
32
+ #
33
+ # Increases the current value by the given amount (defaults to 1).
34
+ #
35
+ # @param [Fixnum] delta the amount by which to increase the current value
36
+ #
37
+ # @return [Fixnum] the current value after incrementation
38
+
39
+ # @!macro atomic_fixnum_method_decrement
40
+ #
41
+ # Decreases the current value by the given amount (defaults to 1).
42
+ #
43
+ # @param [Fixnum] delta the amount by which to decrease the current value
44
+ #
45
+ # @return [Fixnum] the current value after decrementation
46
+
47
+ # @!macro atomic_fixnum_method_compare_and_set
48
+ #
49
+ # Atomically sets the value to the given updated value if the current
50
+ # value == the expected value.
51
+ #
52
+ # @param [Fixnum] expect the expected value
53
+ # @param [Fixnum] update the new value
54
+ #
55
+ # @return [Boolean] true if the value was updated else false
56
+
57
+ # @!macro atomic_fixnum_method_update
58
+ #
59
+ # Pass the current value to the given block, replacing it
60
+ # with the block's result. May retry if the value changes
61
+ # during the block's execution.
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
+ #
67
+ # @return [Object] the new value
68
+
69
+ ###################################################################
70
+
71
+ # @!macro atomic_fixnum_public_api
72
+ #
73
+ # @!method initialize(initial = 0)
74
+ # @!macro atomic_fixnum_method_initialize
75
+ #
76
+ # @!method value
77
+ # @!macro atomic_fixnum_method_value_get
78
+ #
79
+ # @!method value=(value)
80
+ # @!macro atomic_fixnum_method_value_set
81
+ #
82
+ # @!method increment(delta = 1)
83
+ # @!macro atomic_fixnum_method_increment
84
+ #
85
+ # @!method decrement(delta = 1)
86
+ # @!macro atomic_fixnum_method_decrement
87
+ #
88
+ # @!method compare_and_set(expect, update)
89
+ # @!macro atomic_fixnum_method_compare_and_set
90
+ #
91
+ # @!method update
92
+ # @!macro atomic_fixnum_method_update
93
+
94
+ ###################################################################
95
+
96
+ # @!visibility private
97
+ # @!macro internal_implementation_note
98
+ AtomicFixnumImplementation = case
99
+ when defined?(JavaAtomicFixnum)
100
+ JavaAtomicFixnum
101
+ when defined?(CAtomicFixnum)
102
+ CAtomicFixnum
103
+ else
104
+ MutexAtomicFixnum
105
+ end
106
+ private_constant :AtomicFixnumImplementation
107
+
108
+ # @!macro atomic_fixnum
109
+ #
110
+ # A numeric value that can be updated atomically. Reads and writes to an atomic
111
+ # fixnum and thread-safe and guaranteed to succeed. Reads and writes may block
112
+ # briefly but no explicit locking is required.
113
+ #
114
+ # @!macro thread_safe_variable_comparison
115
+ #
116
+ # Performance:
117
+ #
118
+ # ```
119
+ # Testing with ruby 2.1.2
120
+ # Testing with Concurrent::MutexAtomicFixnum...
121
+ # 3.130000 0.000000 3.130000 ( 3.136505)
122
+ # Testing with Concurrent::CAtomicFixnum...
123
+ # 0.790000 0.000000 0.790000 ( 0.785550)
124
+ #
125
+ # Testing with jruby 1.9.3
126
+ # Testing with Concurrent::MutexAtomicFixnum...
127
+ # 5.460000 2.460000 7.920000 ( 3.715000)
128
+ # Testing with Concurrent::JavaAtomicFixnum...
129
+ # 4.520000 0.030000 4.550000 ( 1.187000)
130
+ # ```
131
+ #
132
+ # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong
133
+ #
134
+ # @!macro atomic_fixnum_public_api
135
+ class AtomicFixnum < AtomicFixnumImplementation
136
+ # @return [String] Short string representation.
137
+ def to_s
138
+ format '%s value:%s>', super[0..-2], value
139
+ end
140
+
141
+ alias_method :inspect, :to_s
142
+ end
143
+ end