concurrent-ruby 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
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