concurrent-ruby 1.0.5 → 1.1.6

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 (161) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +115 -0
  3. data/Gemfile +42 -0
  4. data/{LICENSE.txt → LICENSE.md} +2 -0
  5. data/README.md +242 -105
  6. data/Rakefile +332 -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/concurrent-ruby.rb +1 -0
  23. data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +24 -20
  24. data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +7 -7
  25. data/lib/concurrent-ruby/concurrent/array.rb +66 -0
  26. data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +18 -4
  27. data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +10 -10
  28. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/abstract_thread_local_var.rb +0 -0
  29. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +26 -22
  30. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +27 -23
  31. data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +164 -0
  32. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +204 -0
  33. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +7 -7
  34. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +1 -1
  35. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +1 -1
  36. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +9 -6
  37. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_thread_local_var.rb +0 -0
  38. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +2 -0
  39. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +0 -0
  40. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +1 -0
  41. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +0 -0
  42. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +2 -1
  43. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +3 -1
  44. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/ruby_thread_local_var.rb +43 -33
  45. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +8 -8
  46. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/thread_local_var.rb +8 -8
  47. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +3 -8
  48. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +1 -1
  49. data/lib/concurrent-ruby/concurrent/atomics.rb +10 -0
  50. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +0 -0
  51. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +0 -0
  52. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
  53. data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +158 -0
  54. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +3 -3
  55. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +0 -0
  56. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +1 -2
  57. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
  58. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +30 -30
  59. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +0 -0
  60. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
  61. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +3 -3
  62. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/logging.rb +6 -1
  63. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
  64. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +7 -7
  65. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  66. data/lib/{concurrent → concurrent-ruby/concurrent}/configuration.rb +15 -15
  67. data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +1 -1
  68. data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +2 -1
  69. data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +9 -7
  70. data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +0 -0
  71. data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +21 -25
  72. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +19 -25
  73. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +5 -5
  74. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +17 -17
  75. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +27 -30
  76. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
  77. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
  78. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +19 -16
  79. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
  80. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +12 -8
  81. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +0 -2
  82. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
  83. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +9 -4
  84. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +0 -0
  85. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
  86. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +0 -0
  87. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
  88. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +1 -1
  89. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +3 -2
  90. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +6 -6
  91. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +14 -17
  92. data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
  93. data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +4 -1
  94. data/lib/concurrent-ruby/concurrent/hash.rb +59 -0
  95. data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +8 -0
  96. data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +5 -6
  97. data/lib/concurrent-ruby/concurrent/map.rb +337 -0
  98. data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +1 -1
  99. data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +25 -14
  100. data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +2 -2
  101. data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
  102. data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +53 -21
  103. data/lib/concurrent-ruby/concurrent/promises.rb +2167 -0
  104. data/lib/concurrent-ruby/concurrent/re_include.rb +58 -0
  105. data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +0 -0
  106. data/lib/concurrent-ruby/concurrent/set.rb +66 -0
  107. data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +11 -0
  108. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization.rb +4 -5
  109. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +5 -5
  110. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +0 -0
  111. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +18 -4
  112. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +2 -0
  113. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +0 -0
  114. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_object.rb +1 -0
  115. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +2 -0
  116. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +6 -6
  117. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mri_object.rb +1 -0
  118. data/lib/{concurrent/synchronization/mri_lockable_object.rb → concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb} +19 -14
  119. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +53 -23
  120. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_lockable_object.rb +0 -0
  121. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_object.rb +1 -0
  122. data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +47 -0
  123. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/volatile.rb +11 -9
  124. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/synchronized_delegator.rb +0 -0
  125. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
  126. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
  127. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +0 -0
  128. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +63 -0
  129. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
  130. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +9 -4
  131. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
  132. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
  133. data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +5 -2
  134. data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +1 -1
  135. data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +2 -2
  136. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +4 -4
  137. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/monotonic_time.rb +3 -3
  138. data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +79 -0
  139. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +0 -0
  140. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/processor_counter.rb +5 -2
  141. data/lib/concurrent-ruby/concurrent/version.rb +3 -0
  142. metadata +146 -131
  143. data/lib/concurrent/array.rb +0 -39
  144. data/lib/concurrent/atomic/atomic_reference.rb +0 -51
  145. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +0 -8
  146. data/lib/concurrent/atomic_reference/direct_update.rb +0 -81
  147. data/lib/concurrent/atomic_reference/jruby+truffle.rb +0 -2
  148. data/lib/concurrent/atomic_reference/jruby.rb +0 -16
  149. data/lib/concurrent/atomic_reference/rbx.rb +0 -22
  150. data/lib/concurrent/atomic_reference/ruby.rb +0 -32
  151. data/lib/concurrent/atomics.rb +0 -53
  152. data/lib/concurrent/edge.rb +0 -26
  153. data/lib/concurrent/hash.rb +0 -36
  154. data/lib/concurrent/lazy_register.rb +0 -81
  155. data/lib/concurrent/map.rb +0 -240
  156. data/lib/concurrent/synchronization/truffle_lockable_object.rb +0 -9
  157. data/lib/concurrent/synchronization/truffle_object.rb +0 -31
  158. data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +0 -30
  159. data/lib/concurrent/utility/at_exit.rb +0 -97
  160. data/lib/concurrent/utility/native_extension_loader.rb +0 -73
  161. data/lib/concurrent/version.rb +0 -4
@@ -1,51 +0,0 @@
1
- require 'concurrent/synchronization'
2
- require 'concurrent/utility/engine'
3
- require 'concurrent/atomic_reference/concurrent_update_error'
4
- require 'concurrent/atomic_reference/mutex_atomic'
5
-
6
- begin
7
- # force fallback impl with FORCE_ATOMIC_FALLBACK=1
8
- if /[^0fF]/ =~ ENV['FORCE_ATOMIC_FALLBACK']
9
- ruby_engine = 'mutex_atomic'
10
- else
11
- ruby_engine = Concurrent.ruby_engine
12
- end
13
-
14
- require "concurrent/atomic_reference/#{ruby_engine}"
15
- rescue LoadError
16
- #warn 'Compiled extensions not installed, pure Ruby Atomic will be used.'
17
- end
18
-
19
- if defined? Concurrent::JavaAtomicReference
20
-
21
- # @!macro atomic_reference
22
- class Concurrent::AtomicReference < Concurrent::JavaAtomicReference
23
- end
24
-
25
- elsif defined? Concurrent::RbxAtomicReference
26
-
27
- # @!macro atomic_reference
28
- class Concurrent::AtomicReference < Concurrent::RbxAtomicReference
29
- end
30
-
31
- elsif defined? Concurrent::CAtomicReference
32
-
33
- # @!macro atomic_reference
34
- class Concurrent::AtomicReference < Concurrent::CAtomicReference
35
- end
36
-
37
- else
38
-
39
- # @!macro atomic_reference
40
- class Concurrent::AtomicReference < Concurrent::MutexAtomicReference
41
- end
42
- end
43
-
44
- class Concurrent::AtomicReference
45
- # @return [String] Short string representation.
46
- def to_s
47
- format '<#%s:0x%x value:%s>', self.class, object_id << 1, get
48
- end
49
-
50
- alias_method :inspect, :to_s
51
- end
@@ -1,8 +0,0 @@
1
- module Concurrent
2
-
3
- # @!macro atomic_reference
4
- class ConcurrentUpdateError < ThreadError
5
- # frozen pre-allocated backtrace to speed ConcurrentUpdateError
6
- CONC_UP_ERR_BACKTRACE = ['backtrace elided; set verbose to enable'].freeze
7
- end
8
- end
@@ -1,81 +0,0 @@
1
- require 'concurrent/atomic_reference/concurrent_update_error'
2
-
3
- module Concurrent
4
-
5
- # Define update methods that use direct paths
6
- #
7
- # @!visibility private
8
- # @!macro internal_implementation_note
9
- module AtomicDirectUpdate
10
-
11
- # @!macro [attach] atomic_reference_method_update
12
- #
13
- # Pass the current value to the given block, replacing it
14
- # with the block's result. May retry if the value changes
15
- # during the block's execution.
16
- #
17
- # @yield [Object] Calculate a new value for the atomic reference using
18
- # given (old) value
19
- # @yieldparam [Object] old_value the starting value of the atomic reference
20
- #
21
- # @return [Object] the new value
22
- def update
23
- true until compare_and_set(old_value = get, new_value = yield(old_value))
24
- new_value
25
- end
26
-
27
- # @!macro [attach] atomic_reference_method_try_update
28
- #
29
- # Pass the current value to the given block, replacing it
30
- # with the block's result. Return nil if the update fails.
31
- #
32
- # @yield [Object] Calculate a new value for the atomic reference using
33
- # given (old) value
34
- # @yieldparam [Object] old_value the starting value of the atomic reference
35
- #
36
- # @note This method was altered to avoid raising an exception by default.
37
- # Instead, this method now returns `nil` in case of failure. For more info,
38
- # please see: https://github.com/ruby-concurrency/concurrent-ruby/pull/336
39
- #
40
- # @return [Object] the new value, or nil if update failed
41
- def try_update
42
- old_value = get
43
- new_value = yield old_value
44
-
45
- return unless compare_and_set old_value, new_value
46
-
47
- new_value
48
- end
49
-
50
- # @!macro [attach] atomic_reference_method_try_update!
51
- #
52
- # Pass the current value to the given block, replacing it
53
- # with the block's result. Raise an exception if the update
54
- # fails.
55
- #
56
- # @yield [Object] Calculate a new value for the atomic reference using
57
- # given (old) value
58
- # @yieldparam [Object] old_value the starting value of the atomic reference
59
- #
60
- # @note This behavior mimics the behavior of the original
61
- # `AtomicReference#try_update` API. The reason this was changed was to
62
- # avoid raising exceptions (which are inherently slow) by default. For more
63
- # info: https://github.com/ruby-concurrency/concurrent-ruby/pull/336
64
- #
65
- # @return [Object] the new value
66
- #
67
- # @raise [Concurrent::ConcurrentUpdateError] if the update fails
68
- def try_update!
69
- old_value = get
70
- new_value = yield old_value
71
- unless compare_and_set(old_value, new_value)
72
- if $VERBOSE
73
- raise ConcurrentUpdateError, "Update failed"
74
- else
75
- raise ConcurrentUpdateError, "Update failed", ConcurrentUpdateError::CONC_UP_ERR_BACKTRACE
76
- end
77
- end
78
- new_value
79
- end
80
- end
81
- end
@@ -1,2 +0,0 @@
1
- require 'atomic'
2
- require 'concurrent/atomic_reference/rbx'
@@ -1,16 +0,0 @@
1
- require 'concurrent/synchronization'
2
-
3
- if defined?(Concurrent::JavaAtomicReference)
4
- require 'concurrent/atomic_reference/direct_update'
5
-
6
- module Concurrent
7
-
8
- # @!macro atomic_reference
9
- #
10
- # @!visibility private
11
- # @!macro internal_implementation_note
12
- class JavaAtomicReference
13
- include Concurrent::AtomicDirectUpdate
14
- end
15
- end
16
- end
@@ -1,22 +0,0 @@
1
- require 'concurrent/atomic_reference/direct_update'
2
- require 'concurrent/atomic_reference/numeric_cas_wrapper'
3
-
4
- module Concurrent
5
-
6
- # @!macro atomic_reference
7
- #
8
- # @note Extends `Rubinius::AtomicReference` version adding aliases
9
- # and numeric logic.
10
- #
11
- # @!visibility private
12
- # @!macro internal_implementation_note
13
- class RbxAtomicReference < Rubinius::AtomicReference
14
- alias _compare_and_set compare_and_set
15
- include Concurrent::AtomicDirectUpdate
16
- include Concurrent::AtomicNumericCompareAndSetWrapper
17
-
18
- alias_method :value, :get
19
- alias_method :value=, :set
20
- alias_method :swap, :get_and_set
21
- end
22
- end
@@ -1,32 +0,0 @@
1
- if defined? Concurrent::CAtomicReference
2
- require 'concurrent/synchronization'
3
- require 'concurrent/atomic_reference/direct_update'
4
- require 'concurrent/atomic_reference/numeric_cas_wrapper'
5
-
6
- module Concurrent
7
-
8
- # @!macro atomic_reference
9
- #
10
- # @!visibility private
11
- # @!macro internal_implementation_note
12
- class CAtomicReference
13
- include Concurrent::AtomicDirectUpdate
14
- include Concurrent::AtomicNumericCompareAndSetWrapper
15
-
16
- # @!method initialize
17
- # @!macro atomic_reference_method_initialize
18
-
19
- # @!method get
20
- # @!macro atomic_reference_method_get
21
-
22
- # @!method set
23
- # @!macro atomic_reference_method_set
24
-
25
- # @!method get_and_set
26
- # @!macro atomic_reference_method_get_and_set
27
-
28
- # @!method _compare_and_set
29
- # @!macro atomic_reference_method_compare_and_set
30
- end
31
- end
32
- end
@@ -1,53 +0,0 @@
1
- # @!macro [new] atomic_reference
2
- #
3
- # An object reference that may be updated atomically. All read and write
4
- # operations have java volatile semantic.
5
- #
6
- # @!macro thread_safe_variable_comparison
7
- #
8
- # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html
9
- # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html
10
- #
11
- # @!method initialize
12
- # @!macro [new] atomic_reference_method_initialize
13
- # @param [Object] value The initial value.
14
- #
15
- # @!method get
16
- # @!macro [new] atomic_reference_method_get
17
- # Gets the current value.
18
- # @return [Object] the current value
19
- #
20
- # @!method set
21
- # @!macro [new] atomic_reference_method_set
22
- # Sets to the given value.
23
- # @param [Object] new_value the new value
24
- # @return [Object] the new value
25
- #
26
- # @!method get_and_set
27
- # @!macro [new] atomic_reference_method_get_and_set
28
- # Atomically sets to the given value and returns the old value.
29
- # @param [Object] new_value the new value
30
- # @return [Object] the old value
31
- #
32
- # @!method compare_and_set
33
- # @!macro [new] atomic_reference_method_compare_and_set
34
- #
35
- # Atomically sets the value to the given updated value if
36
- # the current value == the expected value.
37
- #
38
- # @param [Object] old_value the expected value
39
- # @param [Object] new_value the new value
40
- #
41
- # @return [Boolean] `true` if successful. A `false` return indicates
42
- # that the actual value was not equal to the expected value.
43
-
44
- require 'concurrent/atomic/atomic_reference'
45
- require 'concurrent/atomic/atomic_boolean'
46
- require 'concurrent/atomic/atomic_fixnum'
47
- require 'concurrent/atomic/cyclic_barrier'
48
- require 'concurrent/atomic/count_down_latch'
49
- require 'concurrent/atomic/event'
50
- require 'concurrent/atomic/read_write_lock'
51
- require 'concurrent/atomic/reentrant_read_write_lock'
52
- require 'concurrent/atomic/semaphore'
53
- require 'concurrent/atomic/thread_local_var'
@@ -1,26 +0,0 @@
1
- module Concurrent
2
-
3
- # A submodule for unstable, highly experimental features that are likely to
4
- # change often and which may never become part of the core gem. Also for
5
- # new, experimental version of abstractions already in the core gem.
6
- #
7
- # Most new features should start in this module, clearly indicating the
8
- # experimental and unstable nature of the feature. Once a feature becomes
9
- # more stable and is a candidate for inclusion in the core gem it should
10
- # be moved up to the `Concurrent` module, where it would reside once merged
11
- # into the core gem.
12
- #
13
- # The only exception to this is for features which *replace* features from
14
- # the core gem in ways that are breaking and not backward compatible. These
15
- # features should remain in this module until merged into the core gem. This
16
- # will prevent namespace collisions.
17
- #
18
- # @!macro [attach] edge_warning
19
- # @api Edge
20
- # @note **Edge Feature:** Edge features are under active development and may change frequently. They are expected not to
21
- # keep backward compatibility (there may also lack tests and documentation). Semantic versions will
22
- # be obeyed though. Features developed in `concurrent-ruby-edge` are expected to move
23
- # to `concurrent-ruby` when final.
24
- module Edge
25
- end
26
- end
@@ -1,36 +0,0 @@
1
- require 'concurrent/utility/engine'
2
- require 'concurrent/thread_safe/util'
3
-
4
- module Concurrent
5
- if Concurrent.on_cruby?
6
-
7
- # @!macro [attach] concurrent_hash
8
- #
9
- # A thread-safe subclass of Hash. This version locks against the object
10
- # itself for every method call, ensuring only one thread can be reading
11
- # or writing at a time. This includes iteration methods like `#each`,
12
- # which takes the lock repeatedly when reading an item.
13
- #
14
- # @see http://ruby-doc.org/core-2.2.0/Hash.html Ruby standard library `Hash`
15
- class Hash < ::Hash;
16
- end
17
-
18
- elsif Concurrent.on_jruby?
19
- require 'jruby/synchronized'
20
-
21
- # @!macro concurrent_hash
22
- class Hash < ::Hash
23
- include JRuby::Synchronized
24
- end
25
-
26
- elsif Concurrent.on_rbx? || Concurrent.on_truffle?
27
- require 'monitor'
28
- require 'concurrent/thread_safe/util/array_hash_rbx'
29
-
30
- # @!macro concurrent_hash
31
- class Hash < ::Hash
32
- end
33
-
34
- ThreadSafe::Util.make_synchronized_on_rbx Hash
35
- end
36
- end
@@ -1,81 +0,0 @@
1
- require 'concurrent/atomic/atomic_reference'
2
- require 'concurrent/delay'
3
-
4
- module Concurrent
5
-
6
- # Hash-like collection that store lazys evaluated values.
7
- #
8
- # @example
9
- # register = Concurrent::LazyRegister.new
10
- # #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @Data=#<Concurrent::AtomicReference:0x007fd7ecd5e1e0>>
11
- # register[:key]
12
- # #=> nil
13
- # register.add(:key) { Concurrent::Actor.spawn!(Actor::AdHoc, :ping) { -> message { message } } }
14
- # #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @Data=#<Concurrent::AtomicReference:0x007fd7ecd5e1e0>>
15
- # register[:key]
16
- # #=> #<Concurrent::Actor::Reference /ping (Concurrent::Actor::AdHoc)>
17
- #
18
- # @!macro edge_warning
19
- class LazyRegister < Synchronization::Object
20
-
21
- private(*attr_atomic(:data))
22
-
23
- def initialize
24
- super
25
- self.data = {}
26
- end
27
-
28
- # Element reference. Retrieves the value object corresponding to the
29
- # key object. Returns nil if the key is not found. Raises an exception
30
- # if the stored item raised an exception when the block was evaluated.
31
- #
32
- # @param [Object] key
33
- # @return [Object] value stored for the key or nil if the key is not found
34
- #
35
- # @raise Exception when the initialization block fails
36
- def [](key)
37
- delay = data[key]
38
- delay ? delay.value! : nil
39
- end
40
-
41
- # Returns true if the given key is present.
42
- #
43
- # @param [Object] key
44
- # @return [true, false] if the key is registered
45
- def registered?(key)
46
- data.key?(key)
47
- end
48
-
49
- alias_method :key?, :registered?
50
- alias_method :has_key?, :registered?
51
-
52
- # Element assignment. Associates the value given by value with the
53
- # key given by key.
54
- #
55
- # @param [Object] key
56
- # @yield the object to store under the key
57
- #
58
- # @return [LazyRegister] self
59
- def register(key, &block)
60
- delay = Delay.new(executor: :immediate, &block)
61
- update_data { |h| h.merge(key => delay) }
62
- self
63
- end
64
-
65
- alias_method :add, :register
66
- alias_method :store, :register
67
-
68
- # Un-registers the object under key, realized or not.
69
- #
70
- # @param [Object] key
71
- #
72
- # @return [LazyRegister] self
73
- def unregister(key)
74
- update_data { |h| h.dup.tap { |j| j.delete(key) } }
75
- self
76
- end
77
-
78
- alias_method :remove, :unregister
79
- alias_method :delete, :unregister
80
- end
81
- end
@@ -1,240 +0,0 @@
1
- require 'thread'
2
- require 'concurrent/constants'
3
- require 'concurrent/synchronization'
4
-
5
- module Concurrent
6
- # @!visibility private
7
- module Collection
8
-
9
- # @!visibility private
10
- MapImplementation = if Concurrent.java_extensions_loaded?
11
- # noinspection RubyResolve
12
- JRubyMapBackend
13
- elsif defined?(RUBY_ENGINE)
14
- case RUBY_ENGINE
15
- when 'ruby'
16
- require 'concurrent/collection/map/mri_map_backend'
17
- MriMapBackend
18
- when 'rbx'
19
- require 'concurrent/collection/map/atomic_reference_map_backend'
20
- AtomicReferenceMapBackend
21
- when 'jruby+truffle'
22
- require 'concurrent/collection/map/atomic_reference_map_backend'
23
- AtomicReferenceMapBackend
24
- else
25
- warn 'Concurrent::Map: unsupported Ruby engine, using a fully synchronized Concurrent::Map implementation' if $VERBOSE
26
- require 'concurrent/collection/map/synchronized_map_backend'
27
- SynchronizedMapBackend
28
- end
29
- else
30
- MriMapBackend
31
- end
32
- end
33
-
34
- # `Concurrent::Map` is a hash-like object and should have much better performance
35
- # characteristics, especially under high concurrency, than `Concurrent::Hash`.
36
- # However, `Concurrent::Map `is not strictly semantically equivalent to a ruby `Hash`
37
- # -- for instance, it does not necessarily retain ordering by insertion time as `Hash`
38
- # does. For most uses it should do fine though, and we recommend you consider
39
- # `Concurrent::Map` instead of `Concurrent::Hash` for your concurrency-safe hash needs.
40
- #
41
- # > require 'concurrent'
42
- # >
43
- # > map = Concurrent::Map.new
44
- class Map < Collection::MapImplementation
45
-
46
- # @!macro [new] map_method_is_atomic
47
- # This method is atomic. Atomic methods of `Map` which accept a block
48
- # do not allow the `self` instance to be used within the block. Doing
49
- # so will cause a deadlock.
50
-
51
- # @!method put_if_absent
52
- # @!macro map_method_is_atomic
53
-
54
- # @!method compute_if_absent
55
- # @!macro map_method_is_atomic
56
-
57
- # @!method compute_if_present
58
- # @!macro map_method_is_atomic
59
-
60
- # @!method compute
61
- # @!macro map_method_is_atomic
62
-
63
- # @!method merge_pair
64
- # @!macro map_method_is_atomic
65
-
66
- # @!method replace_pair
67
- # @!macro map_method_is_atomic
68
-
69
- # @!method replace_if_exists
70
- # @!macro map_method_is_atomic
71
-
72
- # @!method get_and_set
73
- # @!macro map_method_is_atomic
74
-
75
- # @!method delete
76
- # @!macro map_method_is_atomic
77
-
78
- # @!method delete_pair
79
- # @!macro map_method_is_atomic
80
-
81
- def initialize(options = nil, &block)
82
- if options.kind_of?(::Hash)
83
- validate_options_hash!(options)
84
- else
85
- options = nil
86
- end
87
-
88
- super(options)
89
- @default_proc = block
90
- end
91
-
92
- def [](key)
93
- if value = super # non-falsy value is an existing mapping, return it right away
94
- value
95
- # re-check is done with get_or_default(key, NULL) instead of a simple !key?(key) in order to avoid a race condition, whereby by the time the current thread gets to the key?(key) call
96
- # a key => value mapping might have already been created by a different thread (key?(key) would then return true, this elsif branch wouldn't be taken and an incorrent +nil+ value
97
- # would be returned)
98
- # note: nil == value check is not technically necessary
99
- elsif @default_proc && nil == value && NULL == (value = get_or_default(key, NULL))
100
- @default_proc.call(self, key)
101
- else
102
- value
103
- end
104
- end
105
-
106
- alias_method :get, :[]
107
- alias_method :put, :[]=
108
-
109
- # @!macro [attach] map_method_not_atomic
110
- # The "fetch-then-act" methods of `Map` are not atomic. `Map` is intended
111
- # to be use as a concurrency primitive with strong happens-before
112
- # guarantees. It is not intended to be used as a high-level abstraction
113
- # supporting complex operations. All read and write operations are
114
- # thread safe, but no guarantees are made regarding race conditions
115
- # between the fetch operation and yielding to the block. Additionally,
116
- # this method does not support recursion. This is due to internal
117
- # constraints that are very unlikely to change in the near future.
118
- def fetch(key, default_value = NULL)
119
- if NULL != (value = get_or_default(key, NULL))
120
- value
121
- elsif block_given?
122
- yield key
123
- elsif NULL != default_value
124
- default_value
125
- else
126
- raise_fetch_no_key
127
- end
128
- end
129
-
130
- # @!macro map_method_not_atomic
131
- def fetch_or_store(key, default_value = NULL)
132
- fetch(key) do
133
- put(key, block_given? ? yield(key) : (NULL == default_value ? raise_fetch_no_key : default_value))
134
- end
135
- end
136
-
137
- # @!macro map_method_is_atomic
138
- def put_if_absent(key, value)
139
- computed = false
140
- result = compute_if_absent(key) do
141
- computed = true
142
- value
143
- end
144
- computed ? nil : result
145
- end unless method_defined?(:put_if_absent)
146
-
147
- def value?(value)
148
- each_value do |v|
149
- return true if value.equal?(v)
150
- end
151
- false
152
- end
153
-
154
- def keys
155
- arr = []
156
- each_pair {|k, v| arr << k}
157
- arr
158
- end unless method_defined?(:keys)
159
-
160
- def values
161
- arr = []
162
- each_pair {|k, v| arr << v}
163
- arr
164
- end unless method_defined?(:values)
165
-
166
- def each_key
167
- each_pair {|k, v| yield k}
168
- end unless method_defined?(:each_key)
169
-
170
- def each_value
171
- each_pair {|k, v| yield v}
172
- end unless method_defined?(:each_value)
173
-
174
- alias_method :each, :each_pair unless method_defined?(:each)
175
-
176
- def key(value)
177
- each_pair {|k, v| return k if v == value}
178
- nil
179
- end unless method_defined?(:key)
180
- alias_method :index, :key if RUBY_VERSION < '1.9'
181
-
182
- def empty?
183
- each_pair {|k, v| return false}
184
- true
185
- end unless method_defined?(:empty?)
186
-
187
- def size
188
- count = 0
189
- each_pair {|k, v| count += 1}
190
- count
191
- end unless method_defined?(:size)
192
-
193
- def marshal_dump
194
- raise TypeError, "can't dump hash with default proc" if @default_proc
195
- h = {}
196
- each_pair {|k, v| h[k] = v}
197
- h
198
- end
199
-
200
- def marshal_load(hash)
201
- initialize
202
- populate_from(hash)
203
- end
204
-
205
- undef :freeze
206
-
207
- # @!visibility private
208
- DEFAULT_OBJ_ID_STR_WIDTH = 0.size == 4 ? 7 : 14 # we want to look "native", 7 for 32-bit, 14 for 64-bit
209
- # override default #inspect() method: firstly, we don't want to be spilling our guts (i-vars), secondly, MRI backend's
210
- # #inspect() call on its @backend i-var will bump @backend's iter level while possibly yielding GVL
211
- def inspect
212
- id_str = (object_id << 1).to_s(16).rjust(DEFAULT_OBJ_ID_STR_WIDTH, '0')
213
- "#<#{self.class.name}:0x#{id_str} entries=#{size} default_proc=#{@default_proc.inspect}>"
214
- end
215
-
216
- private
217
- def raise_fetch_no_key
218
- raise KeyError, 'key not found'
219
- end
220
-
221
- def initialize_copy(other)
222
- super
223
- populate_from(other)
224
- end
225
-
226
- def populate_from(hash)
227
- hash.each_pair {|k, v| self[k] = v}
228
- self
229
- end
230
-
231
- def validate_options_hash!(options)
232
- if (initial_capacity = options[:initial_capacity]) && (!initial_capacity.kind_of?(Integer) || initial_capacity < 0)
233
- raise ArgumentError, ":initial_capacity must be a positive Integer"
234
- end
235
- if (load_factor = options[:load_factor]) && (!load_factor.kind_of?(Numeric) || load_factor <= 0 || load_factor > 1)
236
- raise ArgumentError, ":load_factor must be a number between 0 and 1"
237
- end
238
- end
239
- end
240
- end