concurrent-ruby 1.0.5 → 1.1.10

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 (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