concurrent-ruby 0.7.0.rc0-x64-mingw32 → 0.7.0.rc1-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +13 -8
  3. data/lib/2.0/concurrent_ruby_ext.so +0 -0
  4. data/lib/concurrent.rb +0 -1
  5. data/lib/concurrent/actress.rb +10 -6
  6. data/lib/concurrent/actress/core.rb +1 -1
  7. data/lib/concurrent/async.rb +39 -74
  8. data/lib/concurrent/atomic.rb +21 -1
  9. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +1 -0
  10. data/lib/concurrent/atomic_reference/direct_update.rb +22 -0
  11. data/lib/concurrent/atomic_reference/jruby.rb +2 -0
  12. data/lib/concurrent/atomic_reference/mutex_atomic.rb +36 -6
  13. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +8 -7
  14. data/lib/concurrent/atomic_reference/rbx.rb +7 -4
  15. data/lib/concurrent/atomic_reference/ruby.rb +2 -0
  16. data/lib/concurrent/executor/executor.rb +118 -70
  17. data/lib/concurrent/executor/immediate_executor.rb +50 -1
  18. data/lib/concurrent/executor/java_fixed_thread_pool.rb +14 -6
  19. data/lib/concurrent/executor/java_single_thread_executor.rb +1 -0
  20. data/lib/concurrent/executor/java_thread_pool_executor.rb +3 -10
  21. data/lib/concurrent/executor/per_thread_executor.rb +80 -4
  22. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +1 -1
  23. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +4 -4
  24. data/lib/concurrent/executor/ruby_single_thread_executor.rb +1 -0
  25. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +2 -0
  26. data/lib/concurrent/executor/serialized_execution.rb +23 -0
  27. data/lib/concurrent/version.rb +1 -1
  28. metadata +2 -4
  29. data/lib/concurrent/atomic_reference/delegated_update.rb +0 -28
  30. 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
- def compare_and_set(expected, new)
7
- if expected.kind_of? Numeric
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 == expected
14
+ return false unless old == old_value
14
15
 
15
- result = _compare_and_set(old, new)
16
+ result = _compare_and_set(old, new_value)
16
17
  return result if result
17
18
  end
18
19
  else
19
- _compare_and_set(expected, new)
20
+ _compare_and_set(old_value, new_value)
20
21
  end
21
22
  end
22
- alias compare_and_swap compare_and_set
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
- # extend Rubinius's version adding aliases and numeric logic
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
- alias value get
13
- alias value= set
14
- alias swap get_and_set
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
- # Submit a task to the executor for asynchronous processing.
66
+ # @!macro [attach] executor_method_post
67
+ #
68
+ # Submit a task to the executor for asynchronous processing.
18
69
  #
19
- # @param [Array] args zero or more arguments to be passed to the task
70
+ # @param [Array] args zero or more arguments to be passed to the task
20
71
  #
21
- # @yield the asynchronous task to perform
72
+ # @yield the asynchronous task to perform
22
73
  #
23
- # @return [Boolean] `true` if the task is queued, `false` if the executor
24
- # is not running
74
+ # @return [Boolean] `true` if the task is queued, `false` if the executor
75
+ # is not running
25
76
  #
26
- # @raise [ArgumentError] if no task is given
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
- # Submit a task to the executor for asynchronous processing.
87
+ # @!macro [attach] executor_method_left_shift
37
88
  #
38
- # @param [Proc] task the asynchronous task to perform
89
+ # Submit a task to the executor for asynchronous processing.
39
90
  #
40
- # @return [self] returns itself
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
- # Is the executor running?
99
+ # @!macro [attach] executor_method_running_question
100
+ #
101
+ # Is the executor running?
47
102
  #
48
- # @return [Boolean] `true` when running, `false` when shutting down or shutdown
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
- # Is the executor shuttingdown?
108
+ # @!macro [attach] executor_method_shuttingdown_question
109
+ #
110
+ # Is the executor shuttingdown?
54
111
  #
55
- # @return [Boolean] `true` when not running and not shutdown, else `false`
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
- # Is the executor shutdown?
117
+ # @!macro [attach] executor_method_shutdown_question
61
118
  #
62
- # @return [Boolean] `true` when shutdown, `false` when shutting down or running
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
- # Begin an orderly shutdown. Tasks already in the queue will be executed,
68
- # but no new tasks will be accepted. Has no additional effect if the
69
- # thread pool is not running.
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
- # Begin an immediate shutdown. In-progress tasks will be allowed to
80
- # complete but enqueued tasks will be dismissed and no new tasks
81
- # will be accepted. Has no additional effect if the thread pool is
82
- # not running.
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
- # Block until executor shutdown is complete or until `timeout` seconds have
94
- # passed.
156
+ # @!macro [attach] executor_method_wait_for_termination
95
157
  #
96
- # @note Does not initiate shutdown or termination. Either `shutdown` or `kill`
97
- # must be called before this method (or on another thread).
158
+ # Block until executor shutdown is complete or until `timeout` seconds have
159
+ # passed.
98
160
  #
99
- # @param [Integer] timeout the maximum number of seconds to wait for shutdown to complete
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
- # @return [Boolean] `true` if shutdown complete or false on `timeout`
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
- # Submit a task to the executor for asynchronous processing.
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{ yield(*args) }
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 => ex
223
+ rescue Java::JavaUtilConcurrent::RejectedExecutionException
153
224
  raise RejectedExecutionError
154
225
  end
155
226
 
156
- # Submit a task to the executor for asynchronous processing.
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
- # Is the executor running?
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
- # Is the executor shuttingdown?
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
- # Is the executor shutdown?
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
- # Block until executor shutdown is complete or until `timeout` seconds have
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
- # Begin an orderly shutdown. Tasks already in the queue will be executed,
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
- # Begin an immediate shutdown. In-progress tasks will be allowed to
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 Executor
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