@@ -12,6 +12,7 @@ module Concurrent
1212 # whereas a `ScheduledTask` is set to execute after a specified delay. This
1313 # implementation is loosely based on Java's
1414 # [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}.
1516 #
1617 # The *intended* schedule time of task execution is set on object construction
1718 # with the `delay` argument. The delay is a numeric (floating point or integer)
@@ -135,19 +136,29 @@ module Concurrent
135136 # #>> The task completed at 2013-11-07 12:26:09 -0500 with value 'What does the fox say?'
136137 #
137138 # @!macro monotonic_clock_warning
139+ #
140+ # @see Concurrent.timer
138141 class ScheduledTask < IVar
139142 include Comparable
140143
144+ # The executor on which to execute the task.
145+ # @!visibility private
141146 attr_reader :executor
142147
143148 # Schedule a task for execution at a specified future time.
144149 #
145- # @yield the task to be performed
146- #
147150 # @param [Float] delay the number of seconds to wait for before executing the task
148151 #
152+ # @yield the task to be performed
153+ #
149154 # @!macro executor_and_deref_options
150155 #
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+ #
151162 # @!macro [attach] deprecated_scheduling_by_clock_time
152163 #
153164 # @note Scheduling is now based on a monotonic clock. This makes the timer much
@@ -158,8 +169,7 @@ def initialize(delay, opts = {}, &task)
158169 raise ArgumentError . new ( 'no block given' ) unless block_given?
159170 super ( IVar ::NO_VALUE , opts , &nil )
160171 synchronize do
161- @original_delay = delay
162- ns_set_delay_and_time! ( delay ) # may raise exception
172+ @delay = calculate_delay! ( delay ) # may raise exception
163173 ns_set_state ( :unscheduled )
164174 @parent = opts . fetch ( :timer_set , Concurrent . global_timer_set )
165175 @args = get_arguments_from ( opts )
@@ -170,20 +180,33 @@ def initialize(delay, opts = {}, &task)
170180 end
171181 end
172182
173- def original_delay
183+ # The `delay` value given at instanciation.
184+ #
185+ # @return [Float] the initial delay.
186+ def initial_delay
174187 synchronize { @delay }
175188 end
176189
177- # @deprecated
190+ # The `delay` value given at instanciation.
191+ #
192+ # @return [Float] the initial delay.
193+ #
194+ # @deprecated use {#initial_delay} instead
178195 def delay
179- warn '[DEPRECATED] use #original_delay instead'
180- original_delay
196+ warn '[DEPRECATED] use #initial_delay instead'
197+ initial_delay
181198 end
182199
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`
183203 def schedule_time
184204 synchronize { @time }
185205 end
186206
207+ # Comparator which orders by schedule time.
208+ #
209+ # @!visibility private
187210 def <=>( other )
188211 self . schedule_time <=> other . schedule_time
189212 end
@@ -206,7 +229,7 @@ def processing?
206229 #
207230 # @return [Boolean] true if the task is in the given state else false
208231 #
209- # @deprecated
232+ # @deprecated Use {#processing?} instead.
210233 def in_progress?
211234 warn '[DEPRECATED] use #processing? instead'
212235 processing?
@@ -215,8 +238,7 @@ def in_progress?
215238 # Cancel this task and prevent it from executing. A task can only be
216239 # cancelled if it is pending or unscheduled.
217240 #
218- # @return [Boolean] true if task execution is successfully cancelled
219- # else false
241+ # @return [Boolean] true if successfully cancelled else false
220242 def cancel
221243 if compare_and_set_state ( :cancelled , :pending , :unscheduled )
222244 complete ( false , nil , CancelledOperationError . new )
@@ -229,23 +251,34 @@ def cancel
229251 end
230252
231253 # 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` .
233255 #
234- # @return [Boolean] true if task execution is successfully cancelled
235- # else false
256+ # @return [Boolean] true if successfully cancelled else false
236257 #
237- # @deprecated
258+ # @deprecated Use {#cancel} instead.
238259 def stop
239260 warn '[DEPRECATED] use #cancel instead'
240261 cancel
241262 end
242263
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
243268 def reset
244269 synchronize { ns_reschedule ( @delay ) }
245270 end
246271
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
247280 def reschedule ( delay )
248- synchronize { ns_reschedule ( delay ) }
281+ synchronize { ns_reschedule ( calculate_delay! ( delay ) ) }
249282 end
250283
251284 # Execute an `:unscheduled` `ScheduledTask`. Immediately sets the state to `:pending`
@@ -255,7 +288,7 @@ def reschedule(delay)
255288 # @return [ScheduledTask] a reference to `self`
256289 def execute
257290 if compare_and_set_state ( :pending , :unscheduled )
258- synchronize { ns_reschedule ( @original_delay , false ) }
291+ synchronize { ns_schedule ( @delay ) }
259292 end
260293 self
261294 end
@@ -276,6 +309,8 @@ def self.execute(delay, opts = {}, &task)
276309 new ( delay , opts , &task ) . execute
277310 end
278311
312+ # Execute the task.
313+ #
279314 # @!visibility private
280315 def process_task
281316 safe_execute ( @task , @args )
@@ -285,20 +320,33 @@ def process_task
285320
286321 protected
287322
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
290332 @time = Concurrent . monotonic_time + @delay
333+ @parent . send ( :post_task , self )
291334 end
292335
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 )
294345 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 )
299347 end
300348
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.
302350 #
303351 # @param [Float] delay the number of seconds to wait for before executing the task
304352 #
0 commit comments