5
5
module Concurrent
6
6
7
7
# `ScheduledTask` is a close relative of `Concurrent::Future` but with one
8
- # important difference. A `Future` is set to execute as soon as possible
9
- # whereas a `ScheduledTask` is set to execute at a specific time . This
8
+ # important difference: A `Future` is set to execute as soon as possible
9
+ # whereas a `ScheduledTask` is set to execute after a specified delay . This
10
10
# implementation is loosely based on Java's
11
11
# [ScheduledExecutorService](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html).
12
12
#
13
13
# The *intended* schedule time of task execution is set on object construction
14
- # with first argument, `delay`. The delay is a numeric (floating point or integer)
14
+ # with the `delay` argument . The delay is a numeric (floating point or integer)
15
15
# representing a number of seconds in the future. Any other value or a numeric
16
16
# equal to or less than zero will result in an exception. The *actual* schedule
17
17
# time of task execution is set when the `execute` method is called.
@@ -95,6 +95,9 @@ module Concurrent
95
95
# task = Concurrent::ScheduledTask.new(2){ 'What does the fox say?' }.execute
96
96
# task.state #=> pending
97
97
#
98
+ # task = Concurrent::ScheduledTask.execute(2){ 'What do you get when you multiply 6 by 9?' }
99
+ # task.state #=> pending
100
+ #
98
101
# @example Failed task execution
99
102
#
100
103
# task = Concurrent::ScheduledTask.execute(2){ raise StandardError.new('Call me maybe?') }
@@ -129,21 +132,32 @@ module Concurrent
129
132
# #>> The task completed at 2013-11-07 12:26:09 -0500 with value 'What does the fox say?'
130
133
#
131
134
# @!macro monotonic_clock_warning
132
- #
133
- # @!macro [attach] deprecated_scheduling_by_clock_time
134
- #
135
- # @note Scheduling is now based on a monotonic clock. This makes the timer much
136
- # more accurate, but only when scheduling by passing a delay in seconds.
137
- # Scheduling a task based on a clock time is deprecated. It will still work
138
- # but will not be supported in the 1.0 release.
139
135
class ScheduledTask < IVar
140
136
141
137
attr_reader :delay
142
138
143
- # @!macro deprecated_scheduling_by_clock_time
139
+ # Schedule a task for execution at a specified future time.
140
+ #
141
+ # @yield the task to be performed
142
+ #
143
+ # @param [Float] delay the number of seconds to wait for before executing the task
144
+ #
145
+ # @param [Hash] opts the options controlling how the future will be processed
146
+ # @option opts [Boolean] :operation (false) when `true` will execute the future on the global
147
+ # operation pool (for long-running operations), when `false` will execute the future on the
148
+ # global task pool (for short-running tasks)
149
+ # @option opts [object] :executor when provided will run all operations on
150
+ # this executor rather than the global thread pool (overrides :operation)
151
+ #
152
+ # @!macro [attach] deprecated_scheduling_by_clock_time
153
+ #
154
+ # @note Scheduling is now based on a monotonic clock. This makes the timer much
155
+ # more accurate, but only when scheduling based on a delay interval.
156
+ # Scheduling a task based on a clock time is deprecated. It will still work
157
+ # but will not be supported in the 1.0 release.
144
158
def initialize ( delay , opts = { } , &block )
145
159
raise ArgumentError . new ( 'no block given' ) unless block_given?
146
- @delay = TimerSet . calculate_interval ( delay )
160
+ @delay = TimerSet . calculate_delay! ( delay )
147
161
148
162
super ( NO_VALUE , opts )
149
163
@@ -153,6 +167,12 @@ def initialize(delay, opts = {}, &block)
153
167
@executor = OptionsParser ::get_executor_from ( opts ) || Concurrent . configuration . global_operation_pool
154
168
end
155
169
170
+
171
+ # Execute an `:unscheduled` `ScheduledTask`. Immediately sets the state to `:pending`
172
+ # and starts counting down toward execution. Does nothing if the `ScheduledTask` is
173
+ # in any state other than `:unscheduled`.
174
+ #
175
+ # @return [ScheduledTask] a reference to `self`
156
176
def execute
157
177
if compare_and_set_state ( :pending , :unscheduled )
158
178
@schedule_time = Time . now + @delay
@@ -161,6 +181,22 @@ def execute
161
181
end
162
182
end
163
183
184
+ # Create a new `ScheduledTask` object with the given block, execute it, and return the
185
+ # `:pending` object.
186
+ #
187
+ # @param [Float] delay the number of seconds to wait for before executing the task
188
+ #
189
+ # @param [Hash] opts the options controlling how the future will be processed
190
+ # @option opts [Boolean] :operation (false) when `true` will execute the future on the global
191
+ # operation pool (for long-running operations), when `false` will execute the future on the
192
+ # global task pool (for short-running tasks)
193
+ # @option opts [object] :executor when provided will run all operations on
194
+ # this executor rather than the global thread pool (overrides :operation)
195
+ #
196
+ # @return [ScheduledTask] the newly created `ScheduledTask` in the `:pending` state
197
+ #
198
+ # @raise [ArgumentError] if no block is given
199
+ #
164
200
# @!macro deprecated_scheduling_by_clock_time
165
201
def self . execute ( delay , opts = { } , &block )
166
202
return ScheduledTask . new ( delay , opts , &block ) . execute
@@ -172,14 +208,25 @@ def schedule_time
172
208
@schedule_time
173
209
end
174
210
211
+ # Has the task been cancelled?
212
+ #
213
+ # @return [Boolean] true if the task is in the given state else false
175
214
def cancelled?
176
215
state == :cancelled
177
216
end
178
217
218
+ # In the task execution in progress?
219
+ #
220
+ # @return [Boolean] true if the task is in the given state else false
179
221
def in_progress?
180
222
state == :in_progress
181
223
end
182
224
225
+ # Cancel this task and prevent it from executing. A task can only be
226
+ # cancelled if it is pending or unscheduled.
227
+ #
228
+ # @return [Boolean] true if task execution is successfully cancelled
229
+ # else false
183
230
def cancel
184
231
if_state ( :unscheduled , :pending ) do
185
232
@state = :cancelled
@@ -193,6 +240,7 @@ def cancel
193
240
194
241
private
195
242
243
+ # @!visibility private
196
244
def process_task
197
245
if compare_and_set_state ( :in_progress , :pending )
198
246
success , val , reason = SafeTaskExecutor . new ( @task ) . execute
0 commit comments