concurrent-ruby 0.7.0.rc0-java → 0.7.0.rc1-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.
- data/README.md +13 -8
- data/lib/concurrent.rb +0 -1
- data/lib/concurrent/actress.rb +10 -6
- data/lib/concurrent/actress/core.rb +1 -1
- data/lib/concurrent/async.rb +39 -74
- data/lib/concurrent/atomic.rb +21 -1
- data/lib/concurrent/atomic_reference/concurrent_update_error.rb +1 -0
- data/lib/concurrent/atomic_reference/direct_update.rb +22 -0
- data/lib/concurrent/atomic_reference/jruby.rb +2 -0
- data/lib/concurrent/atomic_reference/mutex_atomic.rb +36 -6
- data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +8 -7
- data/lib/concurrent/atomic_reference/rbx.rb +7 -4
- data/lib/concurrent/atomic_reference/ruby.rb +2 -0
- data/lib/concurrent/executor/executor.rb +118 -70
- data/lib/concurrent/executor/immediate_executor.rb +50 -1
- data/lib/concurrent/executor/java_fixed_thread_pool.rb +14 -6
- data/lib/concurrent/executor/java_single_thread_executor.rb +1 -0
- data/lib/concurrent/executor/java_thread_pool_executor.rb +3 -10
- data/lib/concurrent/executor/per_thread_executor.rb +80 -4
- data/lib/concurrent/executor/ruby_cached_thread_pool.rb +1 -1
- data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +4 -4
- data/lib/concurrent/executor/ruby_single_thread_executor.rb +1 -0
- data/lib/concurrent/executor/ruby_thread_pool_executor.rb +2 -0
- data/lib/concurrent/executor/serialized_execution.rb +23 -0
- data/lib/concurrent/version.rb +1 -1
- data/lib/concurrent_ruby_ext.bundle +0 -0
- data/lib/concurrent_ruby_ext.jar +0 -0
- metadata +2 -4
- data/lib/concurrent/atomic_reference/delegated_update.rb +0 -28
- data/lib/concurrent/supervisor.rb +0 -343
@@ -1,24 +1,25 @@
|
|
1
1
|
module Concurrent
|
2
2
|
|
3
|
+
# Special "compare and set" handling of numeric values.
|
3
4
|
module AtomicNumericCompareAndSetWrapper
|
4
|
-
#alias _compare_and_set compare_and_set
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
# @!macro atomic_reference_method_compare_and_set
|
7
|
+
def compare_and_set(old_value, new_value)
|
8
|
+
if old_value.kind_of? Numeric
|
8
9
|
while true
|
9
10
|
old = get
|
10
11
|
|
11
12
|
return false unless old.kind_of? Numeric
|
12
13
|
|
13
|
-
return false unless old ==
|
14
|
+
return false unless old == old_value
|
14
15
|
|
15
|
-
result = _compare_and_set(old,
|
16
|
+
result = _compare_and_set(old, new_value)
|
16
17
|
return result if result
|
17
18
|
end
|
18
19
|
else
|
19
|
-
_compare_and_set(
|
20
|
+
_compare_and_set(old_value, new_value)
|
20
21
|
end
|
21
22
|
end
|
22
|
-
|
23
|
+
alias_method :compare_and_swap, :compare_and_set
|
23
24
|
end
|
24
25
|
end
|
@@ -3,14 +3,17 @@ require 'concurrent/atomic_reference/numeric_cas_wrapper'
|
|
3
3
|
|
4
4
|
module Concurrent
|
5
5
|
|
6
|
-
#
|
6
|
+
# @!macro atomic_reference
|
7
|
+
#
|
8
|
+
# @note Extends `Rubinius::AtomicReference` version adding aliases
|
9
|
+
# and numeric logic.
|
7
10
|
class RbxAtomic < Rubinius::AtomicReference
|
8
11
|
alias _compare_and_set compare_and_set
|
9
12
|
include Concurrent::AtomicDirectUpdate
|
10
13
|
include Concurrent::AtomicNumericCompareAndSetWrapper
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
+
alias_method :value, :get
|
16
|
+
alias_method :value=, :set
|
17
|
+
alias_method :swap, :get_and_set
|
15
18
|
end
|
16
19
|
end
|
@@ -9,6 +9,8 @@ require 'concurrent/atomic_reference/direct_update'
|
|
9
9
|
require 'concurrent/atomic_reference/numeric_cas_wrapper'
|
10
10
|
|
11
11
|
module Concurrent
|
12
|
+
|
13
|
+
# @!macro atomic_reference
|
12
14
|
class CAtomic
|
13
15
|
include Concurrent::AtomicDirectUpdate
|
14
16
|
include Concurrent::AtomicNumericCompareAndSetWrapper
|
@@ -5,25 +5,76 @@ require 'concurrent/atomic/event'
|
|
5
5
|
module Concurrent
|
6
6
|
|
7
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`
|
8
16
|
def can_overflow?
|
9
17
|
false
|
10
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
|
11
60
|
end
|
12
61
|
|
13
62
|
module RubyExecutor
|
14
63
|
include Executor
|
15
64
|
include Logging
|
16
65
|
|
17
|
-
#
|
66
|
+
# @!macro [attach] executor_method_post
|
67
|
+
#
|
68
|
+
# Submit a task to the executor for asynchronous processing.
|
18
69
|
#
|
19
|
-
#
|
70
|
+
# @param [Array] args zero or more arguments to be passed to the task
|
20
71
|
#
|
21
|
-
#
|
72
|
+
# @yield the asynchronous task to perform
|
22
73
|
#
|
23
|
-
#
|
24
|
-
#
|
74
|
+
# @return [Boolean] `true` if the task is queued, `false` if the executor
|
75
|
+
# is not running
|
25
76
|
#
|
26
|
-
#
|
77
|
+
# @raise [ArgumentError] if no task is given
|
27
78
|
def post(*args, &task)
|
28
79
|
raise ArgumentError.new('no block given') unless block_given?
|
29
80
|
mutex.synchronize do
|
@@ -33,40 +84,50 @@ module Concurrent
|
|
33
84
|
end
|
34
85
|
end
|
35
86
|
|
36
|
-
#
|
87
|
+
# @!macro [attach] executor_method_left_shift
|
37
88
|
#
|
38
|
-
#
|
89
|
+
# Submit a task to the executor for asynchronous processing.
|
39
90
|
#
|
40
|
-
#
|
91
|
+
# @param [Proc] task the asynchronous task to perform
|
92
|
+
#
|
93
|
+
# @return [self] returns itself
|
41
94
|
def <<(task)
|
42
95
|
post(&task)
|
43
96
|
self
|
44
97
|
end
|
45
98
|
|
46
|
-
#
|
99
|
+
# @!macro [attach] executor_method_running_question
|
100
|
+
#
|
101
|
+
# Is the executor running?
|
47
102
|
#
|
48
|
-
#
|
103
|
+
# @return [Boolean] `true` when running, `false` when shutting down or shutdown
|
49
104
|
def running?
|
50
105
|
! stop_event.set?
|
51
106
|
end
|
52
107
|
|
53
|
-
#
|
108
|
+
# @!macro [attach] executor_method_shuttingdown_question
|
109
|
+
#
|
110
|
+
# Is the executor shuttingdown?
|
54
111
|
#
|
55
|
-
#
|
112
|
+
# @return [Boolean] `true` when not running and not shutdown, else `false`
|
56
113
|
def shuttingdown?
|
57
114
|
! (running? || shutdown?)
|
58
115
|
end
|
59
116
|
|
60
|
-
#
|
117
|
+
# @!macro [attach] executor_method_shutdown_question
|
61
118
|
#
|
62
|
-
#
|
119
|
+
# Is the executor shutdown?
|
120
|
+
#
|
121
|
+
# @return [Boolean] `true` when shutdown, `false` when shutting down or running
|
63
122
|
def shutdown?
|
64
123
|
stopped_event.set?
|
65
124
|
end
|
66
125
|
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
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.
|
70
131
|
def shutdown
|
71
132
|
mutex.synchronize do
|
72
133
|
break unless running?
|
@@ -76,10 +137,12 @@ module Concurrent
|
|
76
137
|
true
|
77
138
|
end
|
78
139
|
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
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.
|
83
146
|
def kill
|
84
147
|
mutex.synchronize do
|
85
148
|
break if shutdown?
|
@@ -90,15 +153,17 @@ module Concurrent
|
|
90
153
|
true
|
91
154
|
end
|
92
155
|
|
93
|
-
#
|
94
|
-
# passed.
|
156
|
+
# @!macro [attach] executor_method_wait_for_termination
|
95
157
|
#
|
96
|
-
#
|
97
|
-
#
|
158
|
+
# Block until executor shutdown is complete or until `timeout` seconds have
|
159
|
+
# passed.
|
98
160
|
#
|
99
|
-
#
|
161
|
+
# @note Does not initiate shutdown or termination. Either `shutdown` or `kill`
|
162
|
+
# must be called before this method (or on another thread).
|
100
163
|
#
|
101
|
-
#
|
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`
|
102
167
|
def wait_for_termination(timeout = nil)
|
103
168
|
stopped_event.wait(timeout)
|
104
169
|
end
|
@@ -107,20 +172,33 @@ module Concurrent
|
|
107
172
|
|
108
173
|
attr_reader :mutex, :stop_event, :stopped_event
|
109
174
|
|
175
|
+
# @!macro [attach] executor_method_init_executor
|
176
|
+
#
|
177
|
+
# Initialize the executor by creating and initializing all the
|
178
|
+
# internal synchronization objects.
|
110
179
|
def init_executor
|
111
180
|
@mutex = Mutex.new
|
112
181
|
@stop_event = Event.new
|
113
182
|
@stopped_event = Event.new
|
114
183
|
end
|
115
184
|
|
185
|
+
# @!macro [attach] executor_method_execute
|
116
186
|
def execute(*args, &task)
|
117
187
|
raise NotImplementedError
|
118
188
|
end
|
119
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.
|
120
194
|
def shutdown_execution
|
121
195
|
stopped_event.set
|
122
196
|
end
|
123
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.
|
124
202
|
def kill_execution
|
125
203
|
# do nothing
|
126
204
|
end
|
@@ -130,49 +208,34 @@ module Concurrent
|
|
130
208
|
|
131
209
|
module JavaExecutor
|
132
210
|
include Executor
|
211
|
+
java_import 'java.lang.Runnable'
|
133
212
|
|
134
|
-
#
|
135
|
-
#
|
136
|
-
# @param [Array] args zero or more arguments to be passed to the task
|
137
|
-
#
|
138
|
-
# @yield the asynchronous task to perform
|
139
|
-
#
|
140
|
-
# @return [Boolean] `true` if the task is queued, `false` if the executor
|
141
|
-
# is not running
|
142
|
-
#
|
143
|
-
# @raise [ArgumentError] if no task is given
|
213
|
+
# @!macro executor_method_post
|
144
214
|
def post(*args)
|
145
215
|
raise ArgumentError.new('no block given') unless block_given?
|
146
216
|
if running?
|
147
|
-
@executor.submit
|
217
|
+
executor_submit = @executor.java_method(:submit, [Runnable.java_class])
|
218
|
+
executor_submit.call { yield(*args) }
|
148
219
|
true
|
149
220
|
else
|
150
221
|
false
|
151
222
|
end
|
152
|
-
rescue Java::JavaUtilConcurrent::RejectedExecutionException
|
223
|
+
rescue Java::JavaUtilConcurrent::RejectedExecutionException
|
153
224
|
raise RejectedExecutionError
|
154
225
|
end
|
155
226
|
|
156
|
-
#
|
157
|
-
#
|
158
|
-
# @param [Proc] task the asynchronous task to perform
|
159
|
-
#
|
160
|
-
# @return [self] returns itself
|
227
|
+
# @!macro executor_method_left_shift
|
161
228
|
def <<(task)
|
162
229
|
post(&task)
|
163
230
|
self
|
164
231
|
end
|
165
232
|
|
166
|
-
#
|
167
|
-
#
|
168
|
-
# @return [Boolean] `true` when running, `false` when shutting down or shutdown
|
233
|
+
# @!macro executor_method_running_question
|
169
234
|
def running?
|
170
235
|
! (shuttingdown? || shutdown?)
|
171
236
|
end
|
172
237
|
|
173
|
-
#
|
174
|
-
#
|
175
|
-
# @return [Boolean] `true` when not running and not shutdown, else `false`
|
238
|
+
# @!macro executor_method_shuttingdown_question
|
176
239
|
def shuttingdown?
|
177
240
|
if @executor.respond_to? :isTerminating
|
178
241
|
@executor.isTerminating
|
@@ -181,38 +244,23 @@ module Concurrent
|
|
181
244
|
end
|
182
245
|
end
|
183
246
|
|
184
|
-
#
|
185
|
-
#
|
186
|
-
# @return [Boolean] `true` when shutdown, `false` when shutting down or running
|
247
|
+
# @!macro executor_method_shutdown_question
|
187
248
|
def shutdown?
|
188
249
|
@executor.isShutdown || @executor.isTerminated
|
189
250
|
end
|
190
251
|
|
191
|
-
#
|
192
|
-
# passed.
|
193
|
-
#
|
194
|
-
# @note Does not initiate shutdown or termination. Either `shutdown` or `kill`
|
195
|
-
# must be called before this method (or on another thread).
|
196
|
-
#
|
197
|
-
# @param [Integer] timeout the maximum number of seconds to wait for shutdown to complete
|
198
|
-
#
|
199
|
-
# @return [Boolean] `true` if shutdown complete or false on `timeout`
|
252
|
+
# @!macro executor_method_wait_for_termination
|
200
253
|
def wait_for_termination(timeout)
|
201
254
|
@executor.awaitTermination(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
|
202
255
|
end
|
203
256
|
|
204
|
-
#
|
205
|
-
# but no new tasks will be accepted. Has no additional effect if the
|
206
|
-
# executor is not running.
|
257
|
+
# @!macro executor_method_shutdown
|
207
258
|
def shutdown
|
208
259
|
@executor.shutdown
|
209
260
|
nil
|
210
261
|
end
|
211
262
|
|
212
|
-
#
|
213
|
-
# complete but enqueued tasks will be dismissed and no new tasks
|
214
|
-
# will be accepted. Has no additional effect if the executor is
|
215
|
-
# not running.
|
263
|
+
# @!macro executor_method_kill
|
216
264
|
def kill
|
217
265
|
@executor.shutdownNow
|
218
266
|
nil
|
@@ -1,16 +1,65 @@
|
|
1
|
+
require 'concurrent/atomic/event'
|
2
|
+
require 'concurrent/executor/executor'
|
3
|
+
|
1
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.
|
2
16
|
class ImmediateExecutor
|
3
|
-
include
|
17
|
+
include SerialExecutor
|
18
|
+
|
19
|
+
# Creates a new executor
|
20
|
+
def initialize
|
21
|
+
@stopped = Concurrent::Event.new
|
22
|
+
end
|
4
23
|
|
24
|
+
# @!macro executor_method_post
|
5
25
|
def post(*args, &task)
|
6
26
|
raise ArgumentError.new('no block given') unless block_given?
|
27
|
+
return false unless running?
|
7
28
|
task.call(*args)
|
8
29
|
true
|
9
30
|
end
|
10
31
|
|
32
|
+
# @!macro executor_method_left_shift
|
11
33
|
def <<(task)
|
12
34
|
post(&task)
|
13
35
|
self
|
14
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
|
15
64
|
end
|
16
65
|
end
|