concurrent-ruby 0.7.0-java

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 (112) hide show
  1. data/LICENSE.txt +21 -0
  2. data/README.md +217 -0
  3. data/lib/concurrent.rb +45 -0
  4. data/lib/concurrent/actor.rb +104 -0
  5. data/lib/concurrent/actor/behaviour.rb +70 -0
  6. data/lib/concurrent/actor/behaviour/abstract.rb +48 -0
  7. data/lib/concurrent/actor/behaviour/awaits.rb +21 -0
  8. data/lib/concurrent/actor/behaviour/buffer.rb +54 -0
  9. data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +12 -0
  10. data/lib/concurrent/actor/behaviour/executes_context.rb +18 -0
  11. data/lib/concurrent/actor/behaviour/linking.rb +42 -0
  12. data/lib/concurrent/actor/behaviour/pausing.rb +77 -0
  13. data/lib/concurrent/actor/behaviour/removes_child.rb +16 -0
  14. data/lib/concurrent/actor/behaviour/sets_results.rb +36 -0
  15. data/lib/concurrent/actor/behaviour/supervised.rb +58 -0
  16. data/lib/concurrent/actor/behaviour/supervising.rb +34 -0
  17. data/lib/concurrent/actor/behaviour/terminates_children.rb +13 -0
  18. data/lib/concurrent/actor/behaviour/termination.rb +54 -0
  19. data/lib/concurrent/actor/context.rb +153 -0
  20. data/lib/concurrent/actor/core.rb +213 -0
  21. data/lib/concurrent/actor/default_dead_letter_handler.rb +9 -0
  22. data/lib/concurrent/actor/envelope.rb +41 -0
  23. data/lib/concurrent/actor/errors.rb +27 -0
  24. data/lib/concurrent/actor/internal_delegations.rb +49 -0
  25. data/lib/concurrent/actor/public_delegations.rb +40 -0
  26. data/lib/concurrent/actor/reference.rb +81 -0
  27. data/lib/concurrent/actor/root.rb +37 -0
  28. data/lib/concurrent/actor/type_check.rb +48 -0
  29. data/lib/concurrent/actor/utils.rb +10 -0
  30. data/lib/concurrent/actor/utils/ad_hoc.rb +21 -0
  31. data/lib/concurrent/actor/utils/balancer.rb +40 -0
  32. data/lib/concurrent/actor/utils/broadcast.rb +52 -0
  33. data/lib/concurrent/actor/utils/pool.rb +59 -0
  34. data/lib/concurrent/actress.rb +3 -0
  35. data/lib/concurrent/agent.rb +230 -0
  36. data/lib/concurrent/async.rb +284 -0
  37. data/lib/concurrent/atomic.rb +91 -0
  38. data/lib/concurrent/atomic/atomic_boolean.rb +202 -0
  39. data/lib/concurrent/atomic/atomic_fixnum.rb +203 -0
  40. data/lib/concurrent/atomic/condition.rb +67 -0
  41. data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +118 -0
  42. data/lib/concurrent/atomic/copy_on_write_observer_set.rb +117 -0
  43. data/lib/concurrent/atomic/count_down_latch.rb +116 -0
  44. data/lib/concurrent/atomic/cyclic_barrier.rb +106 -0
  45. data/lib/concurrent/atomic/event.rb +98 -0
  46. data/lib/concurrent/atomic/synchronization.rb +51 -0
  47. data/lib/concurrent/atomic/thread_local_var.rb +82 -0
  48. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +8 -0
  49. data/lib/concurrent/atomic_reference/direct_update.rb +50 -0
  50. data/lib/concurrent/atomic_reference/jruby.rb +14 -0
  51. data/lib/concurrent/atomic_reference/mutex_atomic.rb +77 -0
  52. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +25 -0
  53. data/lib/concurrent/atomic_reference/rbx.rb +19 -0
  54. data/lib/concurrent/atomic_reference/ruby.rb +37 -0
  55. data/lib/concurrent/atomics.rb +11 -0
  56. data/lib/concurrent/channel/buffered_channel.rb +85 -0
  57. data/lib/concurrent/channel/channel.rb +41 -0
  58. data/lib/concurrent/channel/unbuffered_channel.rb +35 -0
  59. data/lib/concurrent/channel/waitable_list.rb +40 -0
  60. data/lib/concurrent/channels.rb +5 -0
  61. data/lib/concurrent/collection/blocking_ring_buffer.rb +71 -0
  62. data/lib/concurrent/collection/priority_queue.rb +305 -0
  63. data/lib/concurrent/collection/ring_buffer.rb +59 -0
  64. data/lib/concurrent/collections.rb +3 -0
  65. data/lib/concurrent/configuration.rb +161 -0
  66. data/lib/concurrent/dataflow.rb +108 -0
  67. data/lib/concurrent/delay.rb +104 -0
  68. data/lib/concurrent/dereferenceable.rb +101 -0
  69. data/lib/concurrent/errors.rb +30 -0
  70. data/lib/concurrent/exchanger.rb +34 -0
  71. data/lib/concurrent/executor/cached_thread_pool.rb +44 -0
  72. data/lib/concurrent/executor/executor.rb +282 -0
  73. data/lib/concurrent/executor/fixed_thread_pool.rb +33 -0
  74. data/lib/concurrent/executor/immediate_executor.rb +65 -0
  75. data/lib/concurrent/executor/java_cached_thread_pool.rb +31 -0
  76. data/lib/concurrent/executor/java_fixed_thread_pool.rb +41 -0
  77. data/lib/concurrent/executor/java_single_thread_executor.rb +22 -0
  78. data/lib/concurrent/executor/java_thread_pool_executor.rb +180 -0
  79. data/lib/concurrent/executor/per_thread_executor.rb +100 -0
  80. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +29 -0
  81. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +32 -0
  82. data/lib/concurrent/executor/ruby_single_thread_executor.rb +74 -0
  83. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +288 -0
  84. data/lib/concurrent/executor/ruby_thread_pool_worker.rb +72 -0
  85. data/lib/concurrent/executor/safe_task_executor.rb +35 -0
  86. data/lib/concurrent/executor/serialized_execution.rb +126 -0
  87. data/lib/concurrent/executor/single_thread_executor.rb +35 -0
  88. data/lib/concurrent/executor/thread_pool_executor.rb +68 -0
  89. data/lib/concurrent/executor/timer_set.rb +143 -0
  90. data/lib/concurrent/executors.rb +9 -0
  91. data/lib/concurrent/future.rb +125 -0
  92. data/lib/concurrent/ivar.rb +111 -0
  93. data/lib/concurrent/lazy_register.rb +58 -0
  94. data/lib/concurrent/logging.rb +17 -0
  95. data/lib/concurrent/mvar.rb +200 -0
  96. data/lib/concurrent/obligation.rb +171 -0
  97. data/lib/concurrent/observable.rb +40 -0
  98. data/lib/concurrent/options_parser.rb +48 -0
  99. data/lib/concurrent/promise.rb +170 -0
  100. data/lib/concurrent/scheduled_task.rb +79 -0
  101. data/lib/concurrent/timer_task.rb +341 -0
  102. data/lib/concurrent/tvar.rb +248 -0
  103. data/lib/concurrent/utilities.rb +3 -0
  104. data/lib/concurrent/utility/processor_count.rb +152 -0
  105. data/lib/concurrent/utility/timeout.rb +35 -0
  106. data/lib/concurrent/utility/timer.rb +21 -0
  107. data/lib/concurrent/version.rb +3 -0
  108. data/lib/concurrent_ruby.rb +1 -0
  109. data/lib/concurrent_ruby_ext.jar +0 -0
  110. data/lib/concurrent_ruby_ext.so +0 -0
  111. data/lib/extension_helper.rb +28 -0
  112. metadata +163 -0
@@ -0,0 +1,30 @@
1
+ module Concurrent
2
+
3
+ # Raised when errors occur during configuration.
4
+ ConfigurationError = Class.new(StandardError)
5
+
6
+ # Raised when a lifecycle method (such as `stop`) is called in an improper
7
+ # sequence or when the object is in an inappropriate state.
8
+ LifecycleError = Class.new(StandardError)
9
+
10
+ # Raised when an object's methods are called when it has not been
11
+ # properly initialized.
12
+ InitializationError = Class.new(StandardError)
13
+
14
+ # Raised when an object with a start/stop lifecycle has been started an
15
+ # excessive number of times. Often used in conjunction with a restart
16
+ # policy or strategy.
17
+ MaxRestartFrequencyError = Class.new(StandardError)
18
+
19
+ # Raised when an attempt is made to modify an immutable object
20
+ # (such as an `IVar`) after its final state has been set.
21
+ MultipleAssignmentError = Class.new(StandardError)
22
+
23
+ # Raised by an `Executor` when it is unable to process a given task,
24
+ # possibly because of a reject policy or other internal error.
25
+ RejectedExecutionError = Class.new(StandardError)
26
+
27
+ # Raised when an operation times out.
28
+ TimeoutError = Class.new(StandardError)
29
+
30
+ end
@@ -0,0 +1,34 @@
1
+ module Concurrent
2
+ class Exchanger
3
+
4
+ EMPTY = Object.new
5
+
6
+ def initialize(opts = {})
7
+ @first = MVar.new(EMPTY, opts)
8
+ @second = MVar.new(MVar::EMPTY, opts)
9
+ end
10
+
11
+ # @param [Object] value the value to exchange with an other thread
12
+ # @param [Numeric] timeout the maximum time in second to wait for one other thread. nil (default value) means no timeout
13
+ # @return [Object] the value exchanged by the other thread; nil if timed out
14
+ def exchange(value, timeout = nil)
15
+ first = @first.take(timeout)
16
+ if first == MVar::TIMEOUT
17
+ nil
18
+ elsif first == EMPTY
19
+ @first.put value
20
+ second = @second.take timeout
21
+ if second == MVar::TIMEOUT
22
+ nil
23
+ else
24
+ second
25
+ end
26
+ else
27
+ @first.put EMPTY
28
+ @second.put value
29
+ first
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,44 @@
1
+ require 'concurrent/executor/ruby_cached_thread_pool'
2
+
3
+ module Concurrent
4
+
5
+ if RUBY_PLATFORM == 'java'
6
+ require 'concurrent/executor/java_cached_thread_pool'
7
+ # @!macro [attach] cached_thread_pool
8
+ # A thread pool that dynamically grows and shrinks to fit the current workload.
9
+ # New threads are created as needed, existing threads are reused, and threads
10
+ # that remain idle for too long are killed and removed from the pool. These
11
+ # pools are particularly suited to applications that perform a high volume of
12
+ # short-lived tasks.
13
+ #
14
+ # On creation a `CachedThreadPool` has zero running threads. New threads are
15
+ # created on the pool as new operations are `#post`. The size of the pool
16
+ # will grow until `#max_length` threads are in the pool or until the number
17
+ # of threads exceeds the number of running and pending operations. When a new
18
+ # operation is post to the pool the first available idle thread will be tasked
19
+ # with the new operation.
20
+ #
21
+ # Should a thread crash for any reason the thread will immediately be removed
22
+ # from the pool. Similarly, threads which remain idle for an extended period
23
+ # of time will be killed and reclaimed. Thus these thread pools are very
24
+ # efficient at reclaiming unused resources.
25
+ #
26
+ # The API and behavior of this class are based on Java's `CachedThreadPool`
27
+ #
28
+ # @note When running on the JVM (JRuby) this class will inherit from `JavaCachedThreadPool`.
29
+ # On all other platforms it will inherit from `RubyCachedThreadPool`.
30
+ #
31
+ # @see Concurrent::RubyCachedThreadPool
32
+ # @see Concurrent::JavaCachedThreadPool
33
+ #
34
+ # @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
35
+ # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html
36
+ # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html
37
+ class CachedThreadPool < JavaCachedThreadPool
38
+ end
39
+ else
40
+ # @!macro cached_thread_pool
41
+ class CachedThreadPool < RubyCachedThreadPool
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,282 @@
1
+ require 'concurrent/errors'
2
+ require 'concurrent/logging'
3
+ require 'concurrent/atomic/event'
4
+
5
+ module Concurrent
6
+
7
+ module Executor
8
+
9
+ # @!macro [attach] executor_module_method_can_overflow_question
10
+ #
11
+ # Does the task queue have a maximum size?
12
+ #
13
+ # @return [Boolean] True if the task queue has a maximum size else false.
14
+ #
15
+ # @note Always returns `false`
16
+ def can_overflow?
17
+ false
18
+ end
19
+
20
+ # @!macro [attach] executor_module_method_serialized_question
21
+ #
22
+ # Does this executor guarantee serialization of its operations?
23
+ #
24
+ # @return [Boolean] True if the executor guarantees that all operations
25
+ # will be post in the order they are received and no two operations may
26
+ # occur simultaneously. Else false.
27
+ #
28
+ # @note Always returns `false`
29
+ def serialized?
30
+ false
31
+ end
32
+ end
33
+
34
+ # Indicates that the including `Executor` or `ExecutorService` guarantees
35
+ # that all operations will occur in the order they are post and that no
36
+ # two operations may occur simultaneously. This module provides no
37
+ # functionality and provides no guarantees. That is the responsibility
38
+ # of the including class. This module exists solely to allow the including
39
+ # object to be interrogated for its serialization status.
40
+ #
41
+ # @example
42
+ # class Foo
43
+ # include Concurrent::SerialExecutor
44
+ # end
45
+ #
46
+ # foo = Foo.new
47
+ #
48
+ # foo.is_a? Concurrent::Executor #=> true
49
+ # foo.is_a? Concurrent::SerialExecutor #=> true
50
+ # foo.serialized? #=> true
51
+ module SerialExecutor
52
+ include Executor
53
+
54
+ # @!macro executor_module_method_serialized_question
55
+ #
56
+ # @note Always returns `true`
57
+ def serialized?
58
+ true
59
+ end
60
+ end
61
+
62
+ module RubyExecutor
63
+ include Executor
64
+ include Logging
65
+
66
+ # @!macro [attach] executor_method_post
67
+ #
68
+ # Submit a task to the executor for asynchronous processing.
69
+ #
70
+ # @param [Array] args zero or more arguments to be passed to the task
71
+ #
72
+ # @yield the asynchronous task to perform
73
+ #
74
+ # @return [Boolean] `true` if the task is queued, `false` if the executor
75
+ # is not running
76
+ #
77
+ # @raise [ArgumentError] if no task is given
78
+ def post(*args, &task)
79
+ raise ArgumentError.new('no block given') unless block_given?
80
+ mutex.synchronize do
81
+ return false unless running?
82
+ execute(*args, &task)
83
+ true
84
+ end
85
+ end
86
+
87
+ # @!macro [attach] executor_method_left_shift
88
+ #
89
+ # Submit a task to the executor for asynchronous processing.
90
+ #
91
+ # @param [Proc] task the asynchronous task to perform
92
+ #
93
+ # @return [self] returns itself
94
+ def <<(task)
95
+ post(&task)
96
+ self
97
+ end
98
+
99
+ # @!macro [attach] executor_method_running_question
100
+ #
101
+ # Is the executor running?
102
+ #
103
+ # @return [Boolean] `true` when running, `false` when shutting down or shutdown
104
+ def running?
105
+ ! stop_event.set?
106
+ end
107
+
108
+ # @!macro [attach] executor_method_shuttingdown_question
109
+ #
110
+ # Is the executor shuttingdown?
111
+ #
112
+ # @return [Boolean] `true` when not running and not shutdown, else `false`
113
+ def shuttingdown?
114
+ ! (running? || shutdown?)
115
+ end
116
+
117
+ # @!macro [attach] executor_method_shutdown_question
118
+ #
119
+ # Is the executor shutdown?
120
+ #
121
+ # @return [Boolean] `true` when shutdown, `false` when shutting down or running
122
+ def shutdown?
123
+ stopped_event.set?
124
+ end
125
+
126
+ # @!macro [attach] executor_method_shutdown
127
+ #
128
+ # Begin an orderly shutdown. Tasks already in the queue will be executed,
129
+ # but no new tasks will be accepted. Has no additional effect if the
130
+ # thread pool is not running.
131
+ def shutdown
132
+ mutex.synchronize do
133
+ break unless running?
134
+ stop_event.set
135
+ shutdown_execution
136
+ end
137
+ true
138
+ end
139
+
140
+ # @!macro [attach] executor_method_kill
141
+ #
142
+ # Begin an immediate shutdown. In-progress tasks will be allowed to
143
+ # complete but enqueued tasks will be dismissed and no new tasks
144
+ # will be accepted. Has no additional effect if the thread pool is
145
+ # not running.
146
+ def kill
147
+ mutex.synchronize do
148
+ break if shutdown?
149
+ stop_event.set
150
+ kill_execution
151
+ stopped_event.set
152
+ end
153
+ true
154
+ end
155
+
156
+ # @!macro [attach] executor_method_wait_for_termination
157
+ #
158
+ # Block until executor shutdown is complete or until `timeout` seconds have
159
+ # passed.
160
+ #
161
+ # @note Does not initiate shutdown or termination. Either `shutdown` or `kill`
162
+ # must be called before this method (or on another thread).
163
+ #
164
+ # @param [Integer] timeout the maximum number of seconds to wait for shutdown to complete
165
+ #
166
+ # @return [Boolean] `true` if shutdown complete or false on `timeout`
167
+ def wait_for_termination(timeout = nil)
168
+ stopped_event.wait(timeout)
169
+ end
170
+
171
+ protected
172
+
173
+ attr_reader :mutex, :stop_event, :stopped_event
174
+
175
+ # @!macro [attach] executor_method_init_executor
176
+ #
177
+ # Initialize the executor by creating and initializing all the
178
+ # internal synchronization objects.
179
+ def init_executor
180
+ @mutex = Mutex.new
181
+ @stop_event = Event.new
182
+ @stopped_event = Event.new
183
+ end
184
+
185
+ # @!macro [attach] executor_method_execute
186
+ def execute(*args, &task)
187
+ raise NotImplementedError
188
+ end
189
+
190
+ # @!macro [attach] executor_method_shutdown_execution
191
+ #
192
+ # Callback method called when an orderly shutdown has completed.
193
+ # The default behavior is to signal all waiting threads.
194
+ def shutdown_execution
195
+ stopped_event.set
196
+ end
197
+
198
+ # @!macro [attach] executor_method_kill_execution
199
+ #
200
+ # Callback method called when the executor has been killed.
201
+ # The default behavior is to do nothing.
202
+ def kill_execution
203
+ # do nothing
204
+ end
205
+ end
206
+
207
+ if RUBY_PLATFORM == 'java'
208
+
209
+ module JavaExecutor
210
+ include Executor
211
+ java_import 'java.lang.Runnable'
212
+
213
+ # @!macro executor_method_post
214
+ def post(*args)
215
+ raise ArgumentError.new('no block given') unless block_given?
216
+ if running?
217
+ executor_submit = @executor.java_method(:submit, [Runnable.java_class])
218
+ executor_submit.call { yield(*args) }
219
+ true
220
+ else
221
+ false
222
+ end
223
+ rescue Java::JavaUtilConcurrent::RejectedExecutionException
224
+ raise RejectedExecutionError
225
+ end
226
+
227
+ # @!macro executor_method_left_shift
228
+ def <<(task)
229
+ post(&task)
230
+ self
231
+ end
232
+
233
+ # @!macro executor_method_running_question
234
+ def running?
235
+ ! (shuttingdown? || shutdown?)
236
+ end
237
+
238
+ # @!macro executor_method_shuttingdown_question
239
+ def shuttingdown?
240
+ if @executor.respond_to? :isTerminating
241
+ @executor.isTerminating
242
+ else
243
+ false
244
+ end
245
+ end
246
+
247
+ # @!macro executor_method_shutdown_question
248
+ def shutdown?
249
+ @executor.isShutdown || @executor.isTerminated
250
+ end
251
+
252
+ # @!macro executor_method_wait_for_termination
253
+ def wait_for_termination(timeout = nil)
254
+ if timeout.nil?
255
+ ok = @executor.awaitTermination(60, java.util.concurrent.TimeUnit::SECONDS) until ok
256
+ true
257
+ else
258
+ @executor.awaitTermination(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
259
+ end
260
+ end
261
+
262
+ # @!macro executor_method_shutdown
263
+ def shutdown
264
+ @executor.shutdown
265
+ nil
266
+ end
267
+
268
+ # @!macro executor_method_kill
269
+ def kill
270
+ @executor.shutdownNow
271
+ nil
272
+ end
273
+
274
+ protected
275
+
276
+ def set_shutdown_hook
277
+ # without this the process may fail to exit
278
+ at_exit { self.kill }
279
+ end
280
+ end
281
+ end
282
+ end
@@ -0,0 +1,33 @@
1
+ require 'concurrent/executor/ruby_fixed_thread_pool'
2
+
3
+ module Concurrent
4
+
5
+ if RUBY_PLATFORM == 'java'
6
+ require 'concurrent/executor/java_fixed_thread_pool'
7
+ # @!macro [attach] fixed_thread_pool
8
+ #
9
+ # A thread pool with a set number of threads. The number of threads in the pool
10
+ # is set on construction and remains constant. When all threads are busy new
11
+ # tasks `#post` to the thread pool are enqueued until a thread becomes available.
12
+ # Should a thread crash for any reason the thread will immediately be removed
13
+ # from the pool and replaced.
14
+ #
15
+ # The API and behavior of this class are based on Java's `FixedThreadPool`
16
+ #
17
+ # @note When running on the JVM (JRuby) this class will inherit from `JavaFixedThreadPool`.
18
+ # On all other platforms it will inherit from `RubyFixedThreadPool`.
19
+ #
20
+ # @see Concurrent::RubyFixedThreadPool
21
+ # @see Concurrent::JavaFixedThreadPool
22
+ #
23
+ # @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
24
+ # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html
25
+ # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html
26
+ class FixedThreadPool < JavaFixedThreadPool
27
+ end
28
+ else
29
+ # @!macro fixed_thread_pool
30
+ class FixedThreadPool < RubyFixedThreadPool
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,65 @@
1
+ require 'concurrent/atomic/event'
2
+ require 'concurrent/executor/executor'
3
+
4
+ module Concurrent
5
+
6
+ # An executor service which runs all operations on the current thread,
7
+ # blocking as necessary. Operations are performed in the order they are
8
+ # received and no two operations can be performed simultaneously.
9
+ #
10
+ # This executor service exists mainly for testing an debugging. When used
11
+ # it immediately runs every `#post` operation on the current thread, blocking
12
+ # that thread until the operation is complete. This can be very beneficial
13
+ # during testing because it makes all operations deterministic.
14
+ #
15
+ # @note Intended for use primarily in testing and debugging.
16
+ class ImmediateExecutor
17
+ include SerialExecutor
18
+
19
+ # Creates a new executor
20
+ def initialize
21
+ @stopped = Concurrent::Event.new
22
+ end
23
+
24
+ # @!macro executor_method_post
25
+ def post(*args, &task)
26
+ raise ArgumentError.new('no block given') unless block_given?
27
+ return false unless running?
28
+ task.call(*args)
29
+ true
30
+ end
31
+
32
+ # @!macro executor_method_left_shift
33
+ def <<(task)
34
+ post(&task)
35
+ self
36
+ end
37
+
38
+ # @!macro executor_method_running_question
39
+ def running?
40
+ ! shutdown?
41
+ end
42
+
43
+ # @!macro executor_method_shuttingdown_question
44
+ def shuttingdown?
45
+ false
46
+ end
47
+
48
+ # @!macro executor_method_shutdown_question
49
+ def shutdown?
50
+ @stopped.set?
51
+ end
52
+
53
+ # @!macro executor_method_shutdown
54
+ def shutdown
55
+ @stopped.set
56
+ true
57
+ end
58
+ alias_method :kill, :shutdown
59
+
60
+ # @!macro executor_method_wait_for_termination
61
+ def wait_for_termination(timeout = nil)
62
+ @stopped.wait(timeout)
63
+ end
64
+ end
65
+ end