concurrent-ruby 1.0.5 → 1.1.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +155 -0
  3. data/Gemfile +37 -0
  4. data/LICENSE.txt +18 -18
  5. data/README.md +260 -103
  6. data/Rakefile +329 -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 +189 -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 → concurrent-ruby/concurrent}/agent.rb +7 -7
  23. data/lib/concurrent-ruby/concurrent/array.rb +66 -0
  24. data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +28 -24
  25. data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +10 -10
  26. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +26 -22
  27. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +27 -23
  28. data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +164 -0
  29. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +205 -0
  30. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +7 -7
  31. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +1 -1
  32. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +3 -3
  33. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +9 -6
  34. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +2 -0
  35. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +1 -0
  36. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +18 -2
  37. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +2 -1
  38. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +7 -7
  39. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/ruby_thread_local_var.rb +60 -40
  40. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +34 -13
  41. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/thread_local_var.rb +8 -8
  42. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +3 -8
  43. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +1 -1
  44. data/lib/concurrent-ruby/concurrent/atomics.rb +10 -0
  45. data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +158 -0
  46. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +3 -3
  47. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +1 -1
  48. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +1 -2
  49. data/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb +14 -0
  50. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +30 -30
  51. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +11 -1
  52. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +3 -3
  53. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/logging.rb +6 -1
  54. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +7 -7
  55. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  56. data/lib/{concurrent → concurrent-ruby/concurrent}/configuration.rb +15 -15
  57. data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +1 -1
  58. data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +2 -1
  59. data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +9 -7
  60. data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +21 -25
  61. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +35 -38
  62. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +5 -5
  63. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +17 -17
  64. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +47 -33
  65. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +20 -17
  66. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
  67. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +29 -9
  68. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +10 -6
  69. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
  70. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +46 -42
  71. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +5 -5
  72. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +1 -1
  73. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +3 -2
  74. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +7 -6
  75. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +14 -17
  76. data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +4 -1
  77. data/lib/concurrent-ruby/concurrent/hash.rb +59 -0
  78. data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +9 -1
  79. data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +5 -6
  80. data/lib/concurrent-ruby/concurrent/map.rb +346 -0
  81. data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +1 -1
  82. data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +27 -16
  83. data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +2 -2
  84. data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +54 -21
  85. data/lib/concurrent-ruby/concurrent/promises.rb +2167 -0
  86. data/lib/concurrent-ruby/concurrent/re_include.rb +58 -0
  87. data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +29 -16
  88. data/lib/concurrent-ruby/concurrent/set.rb +74 -0
  89. data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +12 -1
  90. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +5 -5
  91. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +18 -4
  92. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +2 -0
  93. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_object.rb +1 -0
  94. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +2 -0
  95. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +8 -10
  96. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mri_object.rb +1 -0
  97. data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +88 -0
  98. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +53 -23
  99. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_lockable_object.rb +6 -0
  100. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_object.rb +1 -0
  101. data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +47 -0
  102. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/volatile.rb +11 -9
  103. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization.rb +4 -5
  104. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +88 -0
  105. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +9 -4
  106. data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +15 -35
  107. data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +1 -1
  108. data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +21 -58
  109. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +4 -4
  110. data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +90 -0
  111. data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +79 -0
  112. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/processor_counter.rb +5 -35
  113. data/lib/concurrent-ruby/concurrent/version.rb +3 -0
  114. data/lib/concurrent-ruby/concurrent-ruby.rb +5 -0
  115. data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +24 -20
  116. metadata +149 -134
  117. data/lib/concurrent/array.rb +0 -39
  118. data/lib/concurrent/atomic/atomic_reference.rb +0 -51
  119. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +0 -8
  120. data/lib/concurrent/atomic_reference/direct_update.rb +0 -81
  121. data/lib/concurrent/atomic_reference/jruby+truffle.rb +0 -2
  122. data/lib/concurrent/atomic_reference/jruby.rb +0 -16
  123. data/lib/concurrent/atomic_reference/rbx.rb +0 -22
  124. data/lib/concurrent/atomic_reference/ruby.rb +0 -32
  125. data/lib/concurrent/atomics.rb +0 -53
  126. data/lib/concurrent/edge.rb +0 -26
  127. data/lib/concurrent/hash.rb +0 -36
  128. data/lib/concurrent/lazy_register.rb +0 -81
  129. data/lib/concurrent/map.rb +0 -240
  130. data/lib/concurrent/synchronization/mri_lockable_object.rb +0 -71
  131. data/lib/concurrent/synchronization/truffle_lockable_object.rb +0 -9
  132. data/lib/concurrent/synchronization/truffle_object.rb +0 -31
  133. data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +0 -30
  134. data/lib/concurrent/utility/at_exit.rb +0 -97
  135. data/lib/concurrent/utility/monotonic_time.rb +0 -58
  136. data/lib/concurrent/utility/native_extension_loader.rb +0 -73
  137. data/lib/concurrent/version.rb +0 -4
  138. /data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/abstract_thread_local_var.rb +0 -0
  139. /data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_thread_local_var.rb +0 -0
  140. /data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +0 -0
  141. /data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +0 -0
  142. /data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +0 -0
  143. /data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
  144. /data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
  145. /data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
  146. /data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
  147. /data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +0 -0
  148. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
  149. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
  150. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
  151. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +0 -0
  152. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
  153. /data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
  154. /data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
  155. /data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +0 -0
  156. /data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +0 -0
  157. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/synchronized_delegator.rb +0 -0
  158. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
  159. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +0 -0
  160. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
  161. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
  162. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
  163. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
  164. /data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +0 -0
@@ -129,7 +129,7 @@ module Concurrent
129
129
  # end
130
130
  # ```
131
131
  #
132
- # @!macro [new] agent_await_warning
132
+ # @!macro agent_await_warning
133
133
  #
134
134
  # **NOTE** Never, *under any circumstances*, call any of the "await" methods
135
135
  # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action
@@ -147,7 +147,7 @@ module Concurrent
147
147
  ERROR_MODES = [:continue, :fail].freeze
148
148
  private_constant :ERROR_MODES
149
149
 
150
- AWAIT_FLAG = Object.new
150
+ AWAIT_FLAG = ::Object.new
151
151
  private_constant :AWAIT_FLAG
152
152
 
153
153
  AWAIT_ACTION = ->(value, latch) { latch.count_down; AWAIT_FLAG }
@@ -242,7 +242,7 @@ module Concurrent
242
242
 
243
243
  alias_method :reason, :error
244
244
 
245
- # @!macro [attach] agent_send
245
+ # @!macro agent_send
246
246
  #
247
247
  # Dispatches an action to the Agent and returns immediately. Subsequently,
248
248
  # in a thread from a thread pool, the {#value} will be set to the return
@@ -271,7 +271,7 @@ module Concurrent
271
271
  # action
272
272
  # @yieldreturn [Object] the new value of the Agent
273
273
  #
274
- # @!macro [attach] send_return
274
+ # @!macro send_return
275
275
  # @return [Boolean] true if the action is successfully enqueued, false if
276
276
  # the Agent is {#failed?}
277
277
  def send(*args, &action)
@@ -280,7 +280,7 @@ module Concurrent
280
280
 
281
281
  # @!macro agent_send
282
282
  #
283
- # @!macro [attach] send_bang_return_and_raise
283
+ # @!macro send_bang_return_and_raise
284
284
  # @return [Boolean] true if the action is successfully enqueued
285
285
  # @raise [Concurrent::Agent::Error] if the Agent is {#failed?}
286
286
  def send!(*args, &action)
@@ -326,7 +326,7 @@ module Concurrent
326
326
  #
327
327
  # @param [Proc] action the action dispatch to be enqueued
328
328
  # @return [Concurrent::Agent] self
329
- # @see {#send_off}
329
+ # @see #send_off
330
330
  def <<(action)
331
331
  send_off(&action)
332
332
  self
@@ -397,7 +397,7 @@ module Concurrent
397
397
 
398
398
  # Is the Agent in a failed state?
399
399
  #
400
- # @see {#restart}
400
+ # @see #restart
401
401
  def failed?
402
402
  !@error.value.nil?
403
403
  end
@@ -0,0 +1,66 @@
1
+ require 'concurrent/utility/engine'
2
+ require 'concurrent/thread_safe/util'
3
+
4
+ module Concurrent
5
+
6
+ # @!macro concurrent_array
7
+ #
8
+ # A thread-safe subclass of Array. This version locks against the object
9
+ # itself for every method call, ensuring only one thread can be reading
10
+ # or writing at a time. This includes iteration methods like `#each`.
11
+ #
12
+ # @note `a += b` is **not** a **thread-safe** operation on
13
+ # `Concurrent::Array`. It reads array `a`, then it creates new `Concurrent::Array`
14
+ # which is concatenation of `a` and `b`, then it writes the concatenation to `a`.
15
+ # The read and write are independent operations they do not form a single atomic
16
+ # operation therefore when two `+=` operations are executed concurrently updates
17
+ # may be lost. Use `#concat` instead.
18
+ #
19
+ # @see http://ruby-doc.org/core/Array.html Ruby standard library `Array`
20
+
21
+ # @!macro internal_implementation_note
22
+ ArrayImplementation = case
23
+ when Concurrent.on_cruby?
24
+ # Array is thread-safe in practice because CRuby runs
25
+ # threads one at a time and does not do context
26
+ # switching during the execution of C functions.
27
+ ::Array
28
+
29
+ when Concurrent.on_jruby?
30
+ require 'jruby/synchronized'
31
+
32
+ class JRubyArray < ::Array
33
+ include JRuby::Synchronized
34
+ end
35
+ JRubyArray
36
+
37
+ when Concurrent.on_rbx?
38
+ require 'monitor'
39
+ require 'concurrent/thread_safe/util/data_structures'
40
+
41
+ class RbxArray < ::Array
42
+ end
43
+
44
+ ThreadSafe::Util.make_synchronized_on_rbx RbxArray
45
+ RbxArray
46
+
47
+ when Concurrent.on_truffleruby?
48
+ require 'concurrent/thread_safe/util/data_structures'
49
+
50
+ class TruffleRubyArray < ::Array
51
+ end
52
+
53
+ ThreadSafe::Util.make_synchronized_on_truffleruby TruffleRubyArray
54
+ TruffleRubyArray
55
+
56
+ else
57
+ warn 'Possibly unsupported Ruby implementation'
58
+ ::Array
59
+ end
60
+ private_constant :ArrayImplementation
61
+
62
+ # @!macro concurrent_array
63
+ class Array < ArrayImplementation
64
+ end
65
+
66
+ end
@@ -58,26 +58,6 @@ module Concurrent
58
58
  # end
59
59
  # ```
60
60
  #
61
- # When defining a constructor it is critical that the first line be a call to
62
- # `super` with no arguments. The `super` method initializes the background
63
- # thread and other asynchronous components.
64
- #
65
- # ```
66
- # class BackgroundLogger
67
- # include Concurrent::Async
68
- #
69
- # def initialize(level)
70
- # super()
71
- # @logger = Logger.new(STDOUT)
72
- # @logger.level = level
73
- # end
74
- #
75
- # def info(msg)
76
- # @logger.info(msg)
77
- # end
78
- # end
79
- # ```
80
- #
81
61
  # Mixing this module into a class provides each object two proxy methods:
82
62
  # `async` and `await`. These methods are thread safe with respect to the
83
63
  # enclosing object. The former proxy allows methods to be called
@@ -159,7 +139,7 @@ module Concurrent
159
139
  #
160
140
  # To get the state *at the current* time, irrespective of an enqueued method
161
141
  # calls, a reader method must be called directly. This is inherently unsafe
162
- # unless the instance variable is itself thread-safe, preferrably using one
142
+ # unless the instance variable is itself thread-safe, preferably using one
163
143
  # of the thread-safe classes within this library. Because the thread-safe
164
144
  # classes within this library are internally-locking or non-locking, they can
165
145
  # be safely used from within asynchronous methods without causing deadlocks.
@@ -188,7 +168,7 @@ module Concurrent
188
168
  #
189
169
  # Class variables should be avoided. Class variables represent shared state.
190
170
  # Shared state is anathema to concurrency. Should there be a need to share
191
- # state using class variables they *must* be thread-safe, preferrably
171
+ # state using class variables they *must* be thread-safe, preferably
192
172
  # using the thread-safe classes within this library. When updating class
193
173
  # variables, never assign a new value/object to the variable itself. Assignment
194
174
  # is not thread-safe in Ruby. Instead, use the thread-safe update functions
@@ -292,6 +272,7 @@ module Concurrent
292
272
  obj.send(:init_synchronization)
293
273
  obj
294
274
  end
275
+ ruby2_keywords :new if respond_to?(:ruby2_keywords, true)
295
276
  end
296
277
  private_constant :ClassMethods
297
278
 
@@ -309,6 +290,7 @@ module Concurrent
309
290
  @delegate = delegate
310
291
  @queue = []
311
292
  @executor = Concurrent.global_io_executor
293
+ @ruby_pid = $$
312
294
  end
313
295
 
314
296
  # Delegates method calls to the wrapped object.
@@ -326,6 +308,7 @@ module Concurrent
326
308
 
327
309
  ivar = Concurrent::IVar.new
328
310
  synchronize do
311
+ reset_if_forked
329
312
  @queue.push [ivar, method, args, block]
330
313
  @executor.post { perform } if @queue.length == 1
331
314
  end
@@ -333,6 +316,13 @@ module Concurrent
333
316
  ivar
334
317
  end
335
318
 
319
+ # Check whether the method is responsive
320
+ #
321
+ # @param [Symbol] method the method being called
322
+ def respond_to_missing?(method, include_private = false)
323
+ @delegate.respond_to?(method) || super
324
+ end
325
+
336
326
  # Perform all enqueued tasks.
337
327
  #
338
328
  # This method must be called from within the executor. It must not be
@@ -354,6 +344,13 @@ module Concurrent
354
344
  end
355
345
  end
356
346
  end
347
+
348
+ def reset_if_forked
349
+ if $$ != @ruby_pid
350
+ @queue.clear
351
+ @ruby_pid = $$
352
+ end
353
+ end
357
354
  end
358
355
  private_constant :AsyncDelegator
359
356
 
@@ -383,6 +380,13 @@ module Concurrent
383
380
  ivar.wait
384
381
  ivar
385
382
  end
383
+
384
+ # Check whether the method is responsive
385
+ #
386
+ # @param [Symbol] method the method being called
387
+ def respond_to_missing?(method, include_private = false)
388
+ @delegate.respond_to?(method) || super
389
+ end
386
390
  end
387
391
  private_constant :AwaitDelegator
388
392
 
@@ -392,7 +396,7 @@ module Concurrent
392
396
  # object's thread. The final disposition of the method call can be obtained
393
397
  # by inspecting the returned future.
394
398
  #
395
- # @!macro [attach] async_thread_safety_warning
399
+ # @!macro async_thread_safety_warning
396
400
  # @note The method call is guaranteed to be thread safe with respect to
397
401
  # all other method calls against the same object that are called with
398
402
  # either `async` or `await`. The mutable nature of Ruby references
@@ -435,7 +439,7 @@ module Concurrent
435
439
  #
436
440
  # @!visibility private
437
441
  def init_synchronization
438
- return self if @__async_initialized__
442
+ return self if defined?(@__async_initialized__) && @__async_initialized__
439
443
  @__async_initialized__ = true
440
444
  @__async_delegator__ = AsyncDelegator.new(self)
441
445
  @__await_delegator__ = AwaitDelegator.new(@__async_delegator__)
@@ -3,7 +3,7 @@ require 'concurrent/collection/copy_on_notify_observer_set'
3
3
  require 'concurrent/concern/observable'
4
4
  require 'concurrent/synchronization'
5
5
 
6
- # @!macro [new] thread_safe_variable_comparison
6
+ # @!macro thread_safe_variable_comparison
7
7
  #
8
8
  # ## Thread-safe Variable Classes
9
9
  #
@@ -18,7 +18,7 @@ require 'concurrent/synchronization'
18
18
  # uncoordinated, *synchronous* change of individual values. Best used when
19
19
  # the value will undergo frequent reads but only occasional, though complex,
20
20
  # updates. Suitable when the result of an update must be known immediately.
21
- # * *{Concurrent::AtomicReference}:* A simple object reference that can be
21
+ # * *{Concurrent::AtomicReference}:* A simple object reference that can be updated
22
22
  # atomically. Updates are synchronous but fast. Best used when updates a
23
23
  # simple set operations. Not suitable when updates are complex.
24
24
  # {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar
@@ -96,8 +96,15 @@ module Concurrent
96
96
  include Concern::Observable
97
97
 
98
98
  safe_initialization!
99
- private(*attr_atomic(:value))
99
+ attr_atomic(:value)
100
+ private :value=, :swap_value, :compare_and_set_value, :update_value
100
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.
101
108
 
102
109
  # Create a new atom with the given initial value.
103
110
  #
@@ -118,13 +125,6 @@ module Concurrent
118
125
  self.value = value
119
126
  end
120
127
 
121
- # @!method value
122
- # The current value of the atom.
123
- #
124
- # @return [Object] The current value.
125
-
126
- alias_method :deref, :value
127
-
128
128
  # Atomically swaps the value of atom using the given block. The current
129
129
  # value will be passed to the block, as will any arguments passed as
130
130
  # arguments to the function. The new value will be validated against the
@@ -5,19 +5,19 @@ module Concurrent
5
5
 
6
6
  ###################################################################
7
7
 
8
- # @!macro [new] atomic_boolean_method_initialize
8
+ # @!macro atomic_boolean_method_initialize
9
9
  #
10
10
  # Creates a new `AtomicBoolean` with the given initial value.
11
11
  #
12
12
  # @param [Boolean] initial the initial value
13
13
 
14
- # @!macro [new] atomic_boolean_method_value_get
14
+ # @!macro atomic_boolean_method_value_get
15
15
  #
16
16
  # Retrieves the current `Boolean` value.
17
17
  #
18
18
  # @return [Boolean] the current value
19
19
 
20
- # @!macro [new] atomic_boolean_method_value_set
20
+ # @!macro atomic_boolean_method_value_set
21
21
  #
22
22
  # Explicitly sets the value.
23
23
  #
@@ -25,33 +25,33 @@ module Concurrent
25
25
  #
26
26
  # @return [Boolean] the current value
27
27
 
28
- # @!macro [new] atomic_boolean_method_true_question
28
+ # @!macro atomic_boolean_method_true_question
29
29
  #
30
30
  # Is the current value `true`
31
31
  #
32
32
  # @return [Boolean] true if the current value is `true`, else false
33
33
 
34
- # @!macro [new] atomic_boolean_method_false_question
34
+ # @!macro atomic_boolean_method_false_question
35
35
  #
36
36
  # Is the current value `false`
37
37
  #
38
38
  # @return [Boolean] true if the current value is `false`, else false
39
39
 
40
- # @!macro [new] atomic_boolean_method_make_true
40
+ # @!macro atomic_boolean_method_make_true
41
41
  #
42
42
  # Explicitly sets the value to true.
43
43
  #
44
- # @return [Boolean] true is value has changed, otherwise false
44
+ # @return [Boolean] true if value has changed, otherwise false
45
45
 
46
- # @!macro [new] atomic_boolean_method_make_false
46
+ # @!macro atomic_boolean_method_make_false
47
47
  #
48
48
  # Explicitly sets the value to false.
49
49
  #
50
- # @return [Boolean] true is value has changed, otherwise false
50
+ # @return [Boolean] true if value has changed, otherwise false
51
51
 
52
52
  ###################################################################
53
53
 
54
- # @!macro [new] atomic_boolean_public_api
54
+ # @!macro atomic_boolean_public_api
55
55
  #
56
56
  # @!method initialize(initial = false)
57
57
  # @!macro atomic_boolean_method_initialize
@@ -88,7 +88,7 @@ module Concurrent
88
88
  end
89
89
  private_constant :AtomicBooleanImplementation
90
90
 
91
- # @!macro [attach] atomic_boolean
91
+ # @!macro atomic_boolean
92
92
  #
93
93
  # A boolean value that can be updated atomically. Reads and writes to an atomic
94
94
  # boolean and thread-safe and guaranteed to succeed. Reads and writes may block
@@ -96,17 +96,21 @@ module Concurrent
96
96
  #
97
97
  # @!macro thread_safe_variable_comparison
98
98
  #
99
- # Testing with ruby 2.1.2
100
- # Testing with Concurrent::MutexAtomicBoolean...
101
- # 2.790000 0.000000 2.790000 ( 2.791454)
102
- # Testing with Concurrent::CAtomicBoolean...
103
- # 0.740000 0.000000 0.740000 ( 0.740206)
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)
104
107
  #
105
- # Testing with jruby 1.9.3
106
- # Testing with Concurrent::MutexAtomicBoolean...
107
- # 5.240000 2.520000 7.760000 ( 3.683000)
108
- # Testing with Concurrent::JavaAtomicBoolean...
109
- # 3.340000 0.010000 3.350000 ( 0.855000)
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
+ # ```
110
114
  #
111
115
  # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html java.util.concurrent.atomic.AtomicBoolean
112
116
  #
@@ -114,7 +118,7 @@ module Concurrent
114
118
  class AtomicBoolean < AtomicBooleanImplementation
115
119
  # @return [String] Short string representation.
116
120
  def to_s
117
- format '<#%s:0x%x value:%s>', self.class, object_id << 1, value
121
+ format '%s value:%s>', super[0..-2], value
118
122
  end
119
123
 
120
124
  alias_method :inspect, :to_s
@@ -5,20 +5,20 @@ module Concurrent
5
5
 
6
6
  ###################################################################
7
7
 
8
- # @!macro [new] atomic_fixnum_method_initialize
8
+ # @!macro atomic_fixnum_method_initialize
9
9
  #
10
10
  # Creates a new `AtomicFixnum` with the given initial value.
11
11
  #
12
12
  # @param [Fixnum] initial the initial value
13
13
  # @raise [ArgumentError] if the initial value is not a `Fixnum`
14
14
 
15
- # @!macro [new] atomic_fixnum_method_value_get
15
+ # @!macro atomic_fixnum_method_value_get
16
16
  #
17
17
  # Retrieves the current `Fixnum` value.
18
18
  #
19
19
  # @return [Fixnum] the current value
20
20
 
21
- # @!macro [new] atomic_fixnum_method_value_set
21
+ # @!macro atomic_fixnum_method_value_set
22
22
  #
23
23
  # Explicitly sets the value.
24
24
  #
@@ -28,7 +28,7 @@ module Concurrent
28
28
  #
29
29
  # @raise [ArgumentError] if the new value is not a `Fixnum`
30
30
 
31
- # @!macro [new] atomic_fixnum_method_increment
31
+ # @!macro atomic_fixnum_method_increment
32
32
  #
33
33
  # Increases the current value by the given amount (defaults to 1).
34
34
  #
@@ -36,7 +36,7 @@ module Concurrent
36
36
  #
37
37
  # @return [Fixnum] the current value after incrementation
38
38
 
39
- # @!macro [new] atomic_fixnum_method_decrement
39
+ # @!macro atomic_fixnum_method_decrement
40
40
  #
41
41
  # Decreases the current value by the given amount (defaults to 1).
42
42
  #
@@ -44,7 +44,7 @@ module Concurrent
44
44
  #
45
45
  # @return [Fixnum] the current value after decrementation
46
46
 
47
- # @!macro [new] atomic_fixnum_method_compare_and_set
47
+ # @!macro atomic_fixnum_method_compare_and_set
48
48
  #
49
49
  # Atomically sets the value to the given updated value if the current
50
50
  # value == the expected value.
@@ -52,9 +52,9 @@ module Concurrent
52
52
  # @param [Fixnum] expect the expected value
53
53
  # @param [Fixnum] update the new value
54
54
  #
55
- # @return [Fixnum] true if the value was updated else false
55
+ # @return [Boolean] true if the value was updated else false
56
56
 
57
- # @!macro [new] atomic_fixnum_method_update
57
+ # @!macro atomic_fixnum_method_update
58
58
  #
59
59
  # Pass the current value to the given block, replacing it
60
60
  # with the block's result. May retry if the value changes
@@ -68,7 +68,7 @@ module Concurrent
68
68
 
69
69
  ###################################################################
70
70
 
71
- # @!macro [new] atomic_fixnum_public_api
71
+ # @!macro atomic_fixnum_public_api
72
72
  #
73
73
  # @!method initialize(initial = 0)
74
74
  # @!macro atomic_fixnum_method_initialize
@@ -79,10 +79,10 @@ module Concurrent
79
79
  # @!method value=(value)
80
80
  # @!macro atomic_fixnum_method_value_set
81
81
  #
82
- # @!method increment
82
+ # @!method increment(delta = 1)
83
83
  # @!macro atomic_fixnum_method_increment
84
84
  #
85
- # @!method decrement
85
+ # @!method decrement(delta = 1)
86
86
  # @!macro atomic_fixnum_method_decrement
87
87
  #
88
88
  # @!method compare_and_set(expect, update)
@@ -105,7 +105,7 @@ module Concurrent
105
105
  end
106
106
  private_constant :AtomicFixnumImplementation
107
107
 
108
- # @!macro [attach] atomic_fixnum
108
+ # @!macro atomic_fixnum
109
109
  #
110
110
  # A numeric value that can be updated atomically. Reads and writes to an atomic
111
111
  # fixnum and thread-safe and guaranteed to succeed. Reads and writes may block
@@ -113,17 +113,21 @@ module Concurrent
113
113
  #
114
114
  # @!macro thread_safe_variable_comparison
115
115
  #
116
- # Testing with ruby 2.1.2
117
- # Testing with Concurrent::MutexAtomicFixnum...
118
- # 3.130000 0.000000 3.130000 ( 3.136505)
119
- # Testing with Concurrent::CAtomicFixnum...
120
- # 0.790000 0.000000 0.790000 ( 0.785550)
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)
121
124
  #
122
- # Testing with jruby 1.9.3
123
- # Testing with Concurrent::MutexAtomicFixnum...
124
- # 5.460000 2.460000 7.920000 ( 3.715000)
125
- # Testing with Concurrent::JavaAtomicFixnum...
126
- # 4.520000 0.030000 4.550000 ( 1.187000)
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
+ # ```
127
131
  #
128
132
  # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong
129
133
  #
@@ -131,7 +135,7 @@ module Concurrent
131
135
  class AtomicFixnum < AtomicFixnumImplementation
132
136
  # @return [String] Short string representation.
133
137
  def to_s
134
- format '<#%s:0x%x value:%s>', self.class, object_id << 1, value
138
+ format '%s value:%s>', super[0..-2], value
135
139
  end
136
140
 
137
141
  alias_method :inspect, :to_s