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
@@ -32,13 +32,13 @@ module Concurrent
32
32
  synchronize{ @value = value }
33
33
  end
34
34
 
35
- # @!macro [attach] dereferenceable_set_deref_options
35
+ # @!macro dereferenceable_set_deref_options
36
36
  # Set the options which define the operations #value performs before
37
37
  # returning data to the caller (dereferencing).
38
38
  #
39
39
  # @note Most classes that include this module will call `#set_deref_options`
40
- # from within the constructor, thus allowing these options to be set at
41
- # object creation.
40
+ # from within the constructor, thus allowing these options to be set at
41
+ # object creation.
42
42
  #
43
43
  # @param [Hash] opts the options defining dereference behavior.
44
44
  # @option opts [String] :dup_on_deref (false) call `#dup` before returning the data
@@ -17,7 +17,12 @@ module Concurrent
17
17
  def log(level, progname, message = nil, &block)
18
18
  #NOTE: Cannot require 'concurrent/configuration' above due to circular references.
19
19
  # Assume that the gem has been initialized if we've gotten this far.
20
- (@logger || Concurrent.global_logger).call level, progname, message, &block
20
+ logger = if defined?(@logger) && @logger
21
+ @logger
22
+ else
23
+ Concurrent.global_logger
24
+ end
25
+ logger.call level, progname, message, &block
21
26
  rescue => error
22
27
  $stderr.puts "`Concurrent.configuration.logger` failed to log #{[level, progname, message, block]}\n" +
23
28
  "#{error.message} (#{error.class})\n#{error.backtrace.join "\n"}"
@@ -49,7 +49,7 @@ module Concurrent
49
49
  # or an AtomicFixum)
50
50
  module Observable
51
51
 
52
- # @!macro [attach] observable_add_observer
52
+ # @!macro observable_add_observer
53
53
  #
54
54
  # Adds an observer to this set. If a block is passed, the observer will be
55
55
  # created by this method and no other params should be passed.
@@ -72,8 +72,8 @@ module Concurrent
72
72
  self
73
73
  end
74
74
 
75
- # @!macro [attach] observable_delete_observer
76
- #
75
+ # @!macro observable_delete_observer
76
+ #
77
77
  # Remove `observer` as an observer on this object so that it will no
78
78
  # longer receive notifications.
79
79
  #
@@ -83,17 +83,17 @@ module Concurrent
83
83
  observers.delete_observer(observer)
84
84
  end
85
85
 
86
- # @!macro [attach] observable_delete_observers
87
- #
86
+ # @!macro observable_delete_observers
87
+ #
88
88
  # Remove all observers associated with this object.
89
- #
89
+ #
90
90
  # @return [Observable] self
91
91
  def delete_observers
92
92
  observers.delete_observers
93
93
  self
94
94
  end
95
95
 
96
- # @!macro [attach] observable_count_observers
96
+ # @!macro observable_count_observers
97
97
  #
98
98
  # Return the number of observers associated with this object.
99
99
  #
@@ -3,12 +3,14 @@ require 'concurrent/delay'
3
3
  require 'concurrent/errors'
4
4
  require 'concurrent/atomic/atomic_reference'
5
5
  require 'concurrent/concern/logging'
6
+ require 'concurrent/concern/deprecation'
6
7
  require 'concurrent/executor/immediate_executor'
7
- require 'concurrent/utility/at_exit'
8
+ require 'concurrent/executor/cached_thread_pool'
8
9
  require 'concurrent/utility/processor_counter'
9
10
 
10
11
  module Concurrent
11
12
  extend Concern::Logging
13
+ extend Concern::Deprecation
12
14
 
13
15
  autoload :Options, 'concurrent/options'
14
16
  autoload :TimerSet, 'concurrent/executor/timer_set'
@@ -96,15 +98,15 @@ module Concurrent
96
98
  end
97
99
 
98
100
  # @!visibility private
99
- GLOBAL_FAST_EXECUTOR = Delay.new { Concurrent.new_fast_executor(auto_terminate: true) }
101
+ GLOBAL_FAST_EXECUTOR = Delay.new { Concurrent.new_fast_executor }
100
102
  private_constant :GLOBAL_FAST_EXECUTOR
101
103
 
102
104
  # @!visibility private
103
- GLOBAL_IO_EXECUTOR = Delay.new { Concurrent.new_io_executor(auto_terminate: true) }
105
+ GLOBAL_IO_EXECUTOR = Delay.new { Concurrent.new_io_executor }
104
106
  private_constant :GLOBAL_IO_EXECUTOR
105
107
 
106
108
  # @!visibility private
107
- GLOBAL_TIMER_SET = Delay.new { TimerSet.new(auto_terminate: true) }
109
+ GLOBAL_TIMER_SET = Delay.new { TimerSet.new }
108
110
  private_constant :GLOBAL_TIMER_SET
109
111
 
110
112
  # @!visibility private
@@ -114,7 +116,7 @@ module Concurrent
114
116
  # Disables AtExit handlers including pool auto-termination handlers.
115
117
  # When disabled it will be the application programmer's responsibility
116
118
  # to ensure that the handlers are shutdown properly prior to application
117
- # exit by calling {AtExit.run} method.
119
+ # exit by calling `AtExit.run` method.
118
120
  #
119
121
  # @note this option should be needed only because of `at_exit` ordering
120
122
  # issues which may arise when running some of the testing frameworks.
@@ -124,9 +126,10 @@ module Concurrent
124
126
  # @note This method should *never* be called
125
127
  # from within a gem. It should *only* be used from within the main
126
128
  # application and even then it should be used only when necessary.
127
- # @see AtExit
129
+ # @deprecated Has no effect since it is no longer needed, see https://github.com/ruby-concurrency/concurrent-ruby/pull/841.
130
+ #
128
131
  def self.disable_at_exit_handlers!
129
- AtExit.enabled = false
132
+ deprecated "Method #disable_at_exit_handlers! has no effect since it is no longer needed, see https://github.com/ruby-concurrency/concurrent-ruby/pull/841."
130
133
  end
131
134
 
132
135
  # Global thread pool optimized for short, fast *operations*.
@@ -170,19 +173,16 @@ module Concurrent
170
173
  auto_terminate: opts.fetch(:auto_terminate, true),
171
174
  idletime: 60, # 1 minute
172
175
  max_queue: 0, # unlimited
173
- fallback_policy: :abort # shouldn't matter -- 0 max queue
176
+ fallback_policy: :abort, # shouldn't matter -- 0 max queue
177
+ name: "fast"
174
178
  )
175
179
  end
176
180
 
177
181
  def self.new_io_executor(opts = {})
178
- ThreadPoolExecutor.new(
179
- min_threads: [2, Concurrent.processor_count].max,
180
- max_threads: ThreadPoolExecutor::DEFAULT_MAX_POOL_SIZE,
181
- # max_threads: 1000,
182
+ CachedThreadPool.new(
182
183
  auto_terminate: opts.fetch(:auto_terminate, true),
183
- idletime: 60, # 1 minute
184
- max_queue: 0, # unlimited
185
- fallback_policy: :abort # shouldn't matter -- 0 max queue
184
+ fallback_policy: :abort, # shouldn't matter -- 0 max queue
185
+ name: "io"
186
186
  )
187
187
  end
188
188
  end
@@ -3,6 +3,6 @@ module Concurrent
3
3
  # Various classes within allows for +nil+ values to be stored,
4
4
  # so a special +NULL+ token is required to indicate the "nil-ness".
5
5
  # @!visibility private
6
- NULL = Object.new
6
+ NULL = ::Object.new
7
7
 
8
8
  end
@@ -18,7 +18,8 @@ module Concurrent
18
18
  end
19
19
  end
20
20
 
21
- # {include:file:doc/dataflow.md}
21
+ # Dataflow allows you to create a task that will be scheduled when all of its data dependencies are available.
22
+ # {include:file:docs-source/dataflow.md}
22
23
  #
23
24
  # @param [Future] inputs zero or more `Future` operations that this dataflow depends upon
24
25
  #
@@ -32,7 +32,7 @@ module Concurrent
32
32
  #
33
33
  # @!macro copy_options
34
34
  #
35
- # @!macro [attach] delay_note_regarding_blocking
35
+ # @!macro delay_note_regarding_blocking
36
36
  # @note The default behavior of `Delay` is to block indefinitely when
37
37
  # calling either `value` or `wait`, executing the delayed operation on
38
38
  # the current thread. This makes the `timeout` value completely
@@ -81,13 +81,15 @@ module Concurrent
81
81
  # this function has been optimized for performance and
82
82
  # should not be modified without running new benchmarks
83
83
  synchronize do
84
- execute = @computing = true unless @computing
84
+ execute = @evaluation_started = true unless @evaluation_started
85
85
  if execute
86
86
  begin
87
87
  set_state(true, @task.call, nil)
88
88
  rescue => ex
89
89
  set_state(false, nil, ex)
90
90
  end
91
+ elsif incomplete?
92
+ raise IllegalOperationError, 'Recursive call to #value during evaluation of the Delay'
91
93
  end
92
94
  end
93
95
  if @do_nothing_on_deref
@@ -144,7 +146,7 @@ module Concurrent
144
146
  def reconfigure(&block)
145
147
  synchronize do
146
148
  raise ArgumentError.new('no block given') unless block_given?
147
- unless @computing
149
+ unless @evaluation_started
148
150
  @task = block
149
151
  true
150
152
  else
@@ -160,9 +162,9 @@ module Concurrent
160
162
  set_deref_options(opts)
161
163
  @executor = opts[:executor]
162
164
 
163
- @task = block
164
- @state = :pending
165
- @computing = false
165
+ @task = block
166
+ @state = :pending
167
+ @evaluation_started = false
166
168
  end
167
169
 
168
170
  private
@@ -173,7 +175,7 @@ module Concurrent
173
175
  # should not be modified without running new benchmarks
174
176
  execute = task = nil
175
177
  synchronize do
176
- execute = @computing = true unless @computing
178
+ execute = @evaluation_started = true unless @evaluation_started
177
179
  task = @task
178
180
  end
179
181
 
@@ -8,7 +8,7 @@ require 'concurrent/utility/monotonic_time'
8
8
 
9
9
  module Concurrent
10
10
 
11
- # @!macro [attach] exchanger
11
+ # @!macro exchanger
12
12
  #
13
13
  # A synchronization point at which threads can pair and swap elements within
14
14
  # pairs. Each thread presents some object on entry to the exchange method,
@@ -24,9 +24,6 @@ module Concurrent
24
24
  # will remain correct.
25
25
  #
26
26
  # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html java.util.concurrent.Exchanger
27
- #
28
- # @!macro edge_warning
29
- #
30
27
  # @example
31
28
  #
32
29
  # exchanger = Concurrent::Exchanger.new
@@ -36,20 +33,19 @@ module Concurrent
36
33
  # Thread.new { puts "second: " << exchanger.exchange('bar', 1) } #=> "second: foo"
37
34
  # ]
38
35
  # threads.each {|t| t.join(2) }
39
- #
36
+
40
37
  # @!visibility private
41
38
  class AbstractExchanger < Synchronization::Object
42
39
 
43
40
  # @!visibility private
44
- CANCEL = Object.new
41
+ CANCEL = ::Object.new
45
42
  private_constant :CANCEL
46
43
 
47
- # @!macro [attach] exchanger_method_initialize
48
44
  def initialize
49
45
  super
50
46
  end
51
47
 
52
- # @!macro [attach] exchanger_method_do_exchange
48
+ # @!macro exchanger_method_do_exchange
53
49
  #
54
50
  # Waits for another thread to arrive at this exchange point (unless the
55
51
  # current thread is interrupted), and then transfers the given object to
@@ -61,7 +57,7 @@ module Concurrent
61
57
  # @param [Object] value the value to exchange with another thread
62
58
  # @param [Numeric, nil] timeout in seconds, `nil` blocks indefinitely
63
59
  #
64
- # @!macro [attach] exchanger_method_exchange
60
+ # @!macro exchanger_method_exchange
65
61
  #
66
62
  # In some edge cases when a `timeout` is given a return value of `nil` may be
67
63
  # ambiguous. Specifically, if `nil` is a valid value in the exchange it will
@@ -75,8 +71,7 @@ module Concurrent
75
71
  end
76
72
 
77
73
  # @!macro exchanger_method_do_exchange
78
- #
79
- # @!macro [attach] exchanger_method_exchange_bang
74
+ # @!macro exchanger_method_exchange_bang
80
75
  #
81
76
  # On timeout a {Concurrent::TimeoutError} exception will be raised.
82
77
  #
@@ -91,8 +86,7 @@ module Concurrent
91
86
  end
92
87
 
93
88
  # @!macro exchanger_method_do_exchange
94
- #
95
- # @!macro [attach] exchanger_method_try_exchange
89
+ # @!macro exchanger_method_try_exchange
96
90
  #
97
91
  # The return value will be a {Concurrent::Maybe} set to `Just` on success or
98
92
  # `Nothing` on timeout.
@@ -130,7 +124,6 @@ module Concurrent
130
124
  end
131
125
  end
132
126
 
133
- # @!macro exchanger
134
127
  # @!macro internal_implementation_note
135
128
  # @!visibility private
136
129
  class RubyExchanger < AbstractExchanger
@@ -148,8 +141,8 @@ module Concurrent
148
141
 
149
142
  def initialize(item)
150
143
  super()
151
- @Item = item
152
- @Latch = Concurrent::CountDownLatch.new
144
+ @Item = item
145
+ @Latch = Concurrent::CountDownLatch.new
153
146
  self.value = nil
154
147
  end
155
148
 
@@ -163,7 +156,6 @@ module Concurrent
163
156
  end
164
157
  private_constant :Node
165
158
 
166
- # @!macro exchanger_method_initialize
167
159
  def initialize
168
160
  super
169
161
  end
@@ -218,7 +210,7 @@ module Concurrent
218
210
  # node's initial value. It never changes. It's what the fulfiller returns on
219
211
  # success. The occupier's hole is where the fulfiller put its item. It's the
220
212
  # item that the occupier returns on success. The latch is used for synchronization.
221
- # Becuase a thread may act as either an occupier or fulfiller (or possibly
213
+ # Because a thread may act as either an occupier or fulfiller (or possibly
222
214
  # both in periods of high contention) every thread creates a node when
223
215
  # the exchange method is first called.
224
216
  #
@@ -260,8 +252,8 @@ module Concurrent
260
252
  # - Wake the sleeping occupier
261
253
  # - Return the occupier's item
262
254
 
263
- value = NULL if value.nil? # The sentinel allows nil to be a valid value
264
- me = Node.new(value) # create my node in case I need to occupy
255
+ value = NULL if value.nil? # The sentinel allows nil to be a valid value
256
+ me = Node.new(value) # create my node in case I need to occupy
265
257
  end_at = Concurrent.monotonic_time + timeout.to_f # The time to give up
266
258
 
267
259
  result = loop do
@@ -298,12 +290,10 @@ module Concurrent
298
290
 
299
291
  if Concurrent.on_jruby?
300
292
 
301
- # @!macro exchanger
302
293
  # @!macro internal_implementation_note
303
294
  # @!visibility private
304
295
  class JavaExchanger < AbstractExchanger
305
296
 
306
- # @!macro exchanger_method_initialize
307
297
  def initialize
308
298
  @exchanger = java.util.concurrent.Exchanger.new
309
299
  end
@@ -314,11 +304,17 @@ module Concurrent
314
304
  #
315
305
  # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout
316
306
  def do_exchange(value, timeout)
307
+ result = nil
317
308
  if timeout.nil?
318
- @exchanger.exchange(value)
309
+ Synchronization::JRuby.sleep_interruptibly do
310
+ result = @exchanger.exchange(value)
311
+ end
319
312
  else
320
- @exchanger.exchange(value, 1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
313
+ Synchronization::JRuby.sleep_interruptibly do
314
+ result = @exchanger.exchange(value, 1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
315
+ end
321
316
  end
317
+ result
322
318
  rescue java.util.concurrent.TimeoutException
323
319
  CANCEL
324
320
  end
@@ -339,7 +335,7 @@ module Concurrent
339
335
  class Exchanger < ExchangerImplementation
340
336
 
341
337
  # @!method initialize
342
- # @!macro exchanger_method_initialize
338
+ # Creates exchanger instance
343
339
 
344
340
  # @!method exchange(value, timeout = nil)
345
341
  # @!macro exchanger_method_do_exchange
@@ -1,7 +1,7 @@
1
1
  require 'concurrent/errors'
2
+ require 'concurrent/concern/deprecation'
2
3
  require 'concurrent/executor/executor_service'
3
4
  require 'concurrent/synchronization'
4
- require 'concurrent/utility/at_exit'
5
5
 
6
6
  module Concurrent
7
7
 
@@ -9,6 +9,7 @@ module Concurrent
9
9
  # @!visibility private
10
10
  class AbstractExecutorService < Synchronization::LockableObject
11
11
  include ExecutorService
12
+ include Concern::Deprecation
12
13
 
13
14
  # The set of possible fallback policies that may be set at thread pool creation.
14
15
  FALLBACK_POLICIES = [:abort, :discard, :caller_runs].freeze
@@ -16,10 +17,20 @@ module Concurrent
16
17
  # @!macro executor_service_attr_reader_fallback_policy
17
18
  attr_reader :fallback_policy
18
19
 
20
+ attr_reader :name
21
+
19
22
  # Create a new thread pool.
20
- def initialize(*args, &block)
23
+ def initialize(opts = {}, &block)
21
24
  super(&nil)
22
- synchronize { ns_initialize(*args, &block) }
25
+ synchronize do
26
+ @auto_terminate = opts.fetch(:auto_terminate, true)
27
+ @name = opts.fetch(:name) if opts.key?(:name)
28
+ ns_initialize(opts, &block)
29
+ end
30
+ end
31
+
32
+ def to_s
33
+ name ? "#{super[0..-2]} name: #{name}>" : super
23
34
  end
24
35
 
25
36
  # @!macro executor_service_method_shutdown
@@ -54,12 +65,12 @@ module Concurrent
54
65
 
55
66
  # @!macro executor_service_method_auto_terminate_question
56
67
  def auto_terminate?
57
- synchronize { ns_auto_terminate? }
68
+ synchronize { @auto_terminate }
58
69
  end
59
70
 
60
71
  # @!macro executor_service_method_auto_terminate_setter
61
72
  def auto_terminate=(value)
62
- synchronize { self.ns_auto_terminate = value }
73
+ deprecated "Method #auto_terminate= has no effect. Set :auto_terminate option when executor is initialized."
63
74
  end
64
75
 
65
76
  private
@@ -93,7 +104,7 @@ module Concurrent
93
104
  raise NotImplementedError
94
105
  end
95
106
 
96
- # @!macro [attach] executor_service_method_ns_shutdown_execution
107
+ # @!macro executor_service_method_ns_shutdown_execution
97
108
  #
98
109
  # Callback method called when an orderly shutdown has completed.
99
110
  # The default behavior is to signal all waiting threads.
@@ -101,7 +112,7 @@ module Concurrent
101
112
  # do nothing
102
113
  end
103
114
 
104
- # @!macro [attach] executor_service_method_ns_kill_execution
115
+ # @!macro executor_service_method_ns_kill_execution
105
116
  #
106
117
  # Callback method called when the executor has been killed.
107
118
  # The default behavior is to do nothing.
@@ -110,25 +121,8 @@ module Concurrent
110
121
  end
111
122
 
112
123
  def ns_auto_terminate?
113
- !!@auto_terminate
124
+ @auto_terminate
114
125
  end
115
126
 
116
- def ns_auto_terminate=(value)
117
- case value
118
- when true
119
- AtExit.add(self) { terminate_at_exit }
120
- @auto_terminate = true
121
- when false
122
- AtExit.delete(self)
123
- @auto_terminate = false
124
- else
125
- raise ArgumentError
126
- end
127
- end
128
-
129
- def terminate_at_exit
130
- kill # TODO be gentle first
131
- wait_for_termination(10)
132
- end
133
127
  end
134
128
  end