@@ -12,6 +12,7 @@ module Concurrent
12
12
# whereas a `ScheduledTask` is set to execute after a specified delay. This
13
13
# implementation is loosely based on Java's
14
14
# [ScheduledExecutorService](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html).
15
+ # It is a more feature-rich variant of {Concurrent.timer}.
15
16
#
16
17
# The *intended* schedule time of task execution is set on object construction
17
18
# with the `delay` argument. The delay is a numeric (floating point or integer)
@@ -135,19 +136,29 @@ module Concurrent
135
136
# #>> The task completed at 2013-11-07 12:26:09 -0500 with value 'What does the fox say?'
136
137
#
137
138
# @!macro monotonic_clock_warning
139
+ #
140
+ # @see Concurrent.timer
138
141
class ScheduledTask < IVar
139
142
include Comparable
140
143
144
+ # The executor on which to execute the task.
145
+ # @!visibility private
141
146
attr_reader :executor
142
147
143
148
# Schedule a task for execution at a specified future time.
144
149
#
145
- # @yield the task to be performed
146
- #
147
150
# @param [Float] delay the number of seconds to wait for before executing the task
148
151
#
152
+ # @yield the task to be performed
153
+ #
149
154
# @!macro executor_and_deref_options
150
155
#
156
+ # @option opts [object, Array] :args zero or more arguments to be passed the task
157
+ # block on execution
158
+ #
159
+ # @raise [ArgumentError] When no block is given
160
+ # @raise [ArgumentError] When given a time that is in the past
161
+ #
151
162
# @!macro [attach] deprecated_scheduling_by_clock_time
152
163
#
153
164
# @note Scheduling is now based on a monotonic clock. This makes the timer much
@@ -158,8 +169,7 @@ def initialize(delay, opts = {}, &task)
158
169
raise ArgumentError . new ( 'no block given' ) unless block_given?
159
170
super ( IVar ::NO_VALUE , opts , &nil )
160
171
synchronize do
161
- @original_delay = delay
162
- ns_set_delay_and_time! ( delay ) # may raise exception
172
+ @delay = calculate_delay! ( delay ) # may raise exception
163
173
ns_set_state ( :unscheduled )
164
174
@parent = opts . fetch ( :timer_set , Concurrent . global_timer_set )
165
175
@args = get_arguments_from ( opts )
@@ -170,20 +180,33 @@ def initialize(delay, opts = {}, &task)
170
180
end
171
181
end
172
182
173
- def original_delay
183
+ # The `delay` value given at instanciation.
184
+ #
185
+ # @return [Float] the initial delay.
186
+ def initial_delay
174
187
synchronize { @delay }
175
188
end
176
189
177
- # @deprecated
190
+ # The `delay` value given at instanciation.
191
+ #
192
+ # @return [Float] the initial delay.
193
+ #
194
+ # @deprecated use {#initial_delay} instead
178
195
def delay
179
- warn '[DEPRECATED] use #original_delay instead'
180
- original_delay
196
+ warn '[DEPRECATED] use #initial_delay instead'
197
+ initial_delay
181
198
end
182
199
200
+ # The monotonic time at which the the task is scheduled to be executed.
201
+ #
202
+ # @return [Float] the schedule time or nil if `unscheduled`
183
203
def schedule_time
184
204
synchronize { @time }
185
205
end
186
206
207
+ # Comparator which orders by schedule time.
208
+ #
209
+ # @!visibility private
187
210
def <=>( other )
188
211
self . schedule_time <=> other . schedule_time
189
212
end
@@ -206,7 +229,7 @@ def processing?
206
229
#
207
230
# @return [Boolean] true if the task is in the given state else false
208
231
#
209
- # @deprecated
232
+ # @deprecated Use {#processing?} instead.
210
233
def in_progress?
211
234
warn '[DEPRECATED] use #processing? instead'
212
235
processing?
@@ -215,8 +238,7 @@ def in_progress?
215
238
# Cancel this task and prevent it from executing. A task can only be
216
239
# cancelled if it is pending or unscheduled.
217
240
#
218
- # @return [Boolean] true if task execution is successfully cancelled
219
- # else false
241
+ # @return [Boolean] true if successfully cancelled else false
220
242
def cancel
221
243
if compare_and_set_state ( :cancelled , :pending , :unscheduled )
222
244
complete ( false , nil , CancelledOperationError . new )
@@ -229,23 +251,34 @@ def cancel
229
251
end
230
252
231
253
# Cancel this task and prevent it from executing. A task can only be
232
- # cancelled if it is pending or unscheduled.
254
+ # cancelled if it is `: pending` or `: unscheduled` .
233
255
#
234
- # @return [Boolean] true if task execution is successfully cancelled
235
- # else false
256
+ # @return [Boolean] true if successfully cancelled else false
236
257
#
237
- # @deprecated
258
+ # @deprecated Use {#cancel} instead.
238
259
def stop
239
260
warn '[DEPRECATED] use #cancel instead'
240
261
cancel
241
262
end
242
263
264
+ # Reschedule the task using the original delay and the current time.
265
+ # A task can only be reset while it is `:pending`.
266
+ #
267
+ # @return [Boolean] true if successfully rescheduled else false
243
268
def reset
244
269
synchronize { ns_reschedule ( @delay ) }
245
270
end
246
271
272
+ # Reschedule the task using the given delay and the current time.
273
+ # A task can only be reset while it is `:pending`.
274
+ #
275
+ # @param [Float] delay the number of seconds to wait for before executing the task
276
+ #
277
+ # @return [Boolean] true if successfully rescheduled else false
278
+ #
279
+ # @raise [ArgumentError] When given a time that is in the past
247
280
def reschedule ( delay )
248
- synchronize { ns_reschedule ( delay ) }
281
+ synchronize { ns_reschedule ( calculate_delay! ( delay ) ) }
249
282
end
250
283
251
284
# Execute an `:unscheduled` `ScheduledTask`. Immediately sets the state to `:pending`
@@ -255,7 +288,7 @@ def reschedule(delay)
255
288
# @return [ScheduledTask] a reference to `self`
256
289
def execute
257
290
if compare_and_set_state ( :pending , :unscheduled )
258
- synchronize { ns_reschedule ( @original_delay , false ) }
291
+ synchronize { ns_schedule ( @delay ) }
259
292
end
260
293
self
261
294
end
@@ -276,6 +309,8 @@ def self.execute(delay, opts = {}, &task)
276
309
new ( delay , opts , &task ) . execute
277
310
end
278
311
312
+ # Execute the task.
313
+ #
279
314
# @!visibility private
280
315
def process_task
281
316
safe_execute ( @task , @args )
@@ -285,20 +320,33 @@ def process_task
285
320
286
321
protected
287
322
288
- def ns_set_delay_and_time! ( delay )
289
- @delay = calculate_delay! ( delay )
323
+ # Schedule the task using the given delay and the current time.
324
+ #
325
+ # @param [Float] delay the number of seconds to wait for before executing the task
326
+ #
327
+ # @return [Boolean] true if successfully rescheduled else false
328
+ #
329
+ # @!visibility private
330
+ def ns_schedule ( delay )
331
+ @delay = delay
290
332
@time = Concurrent . monotonic_time + @delay
333
+ @parent . send ( :post_task , self )
291
334
end
292
335
293
- def ns_reschedule ( delay , fail_if_cannot_remove = true )
336
+ # Reschedule the task using the given delay and the current time.
337
+ # A task can only be reset while it is `:pending`.
338
+ #
339
+ # @param [Float] delay the number of seconds to wait for before executing the task
340
+ #
341
+ # @return [Boolean] true if successfully rescheduled else false
342
+ #
343
+ # @!visibility private
344
+ def ns_reschedule ( delay )
294
345
return false unless ns_check_state? ( :pending )
295
- ns_set_delay_and_time! ( delay )
296
- removed = @parent . send ( :remove_task , self )
297
- return false if fail_if_cannot_remove && !removed
298
- @parent . send ( :post_task , self )
346
+ @parent . send ( :remove_task , self ) && ns_schedule ( delay )
299
347
end
300
348
301
- # Schedule a task to be executed after a given delay (in seconds) .
349
+ # Calculate the actual delay in seconds based on the given delay.
302
350
#
303
351
# @param [Float] delay the number of seconds to wait for before executing the task
304
352
#
0 commit comments