1
- require 'concurrent/obligation'
2
- require 'concurrent/observable'
1
+ require 'concurrent/ivar'
3
2
require 'concurrent/safe_task_executor'
3
+ require 'concurrent/utilities'
4
4
5
5
module Concurrent
6
6
7
- class ScheduledTask
8
- include Obligation
9
- include Concurrent ::Observable
7
+ class ScheduledTask < IVar
10
8
11
9
SchedulingError = Class . new ( ArgumentError )
12
10
@@ -16,20 +14,19 @@ def initialize(schedule_time, opts = {}, &block)
16
14
raise SchedulingError . new ( 'no block given' ) unless block_given?
17
15
calculate_schedule_time! ( schedule_time ) # raise exception if in past
18
16
19
- init_obligation
20
- self . observers = CopyOnWriteObserverSet . new
17
+ super ( NO_VALUE , opts )
18
+
21
19
@state = :unscheduled
22
20
@intended_schedule_time = schedule_time
23
21
@schedule_time = nil
24
22
@task = block
25
- set_deref_options ( opts )
26
23
end
27
24
28
25
# @since 0.5.0
29
26
def execute
30
27
if compare_and_set_state ( :pending , :unscheduled )
31
28
@schedule_time = calculate_schedule_time! ( @intended_schedule_time ) . freeze
32
- Thread . new { work }
29
+ do_next_interval
33
30
self
34
31
end
35
32
end
@@ -54,20 +51,19 @@ def cancel
54
51
true
55
52
end
56
53
end
57
-
58
54
alias_method :stop , :cancel
59
55
60
- def add_observer ( observer , func = :update )
56
+ def add_observer ( * args )
61
57
if_state ( :unscheduled , :pending , :in_progress ) do
62
- observers . add_observer ( observer , func )
58
+ observers . add_observer ( * args )
63
59
end
64
60
end
65
61
66
- protected
62
+ protected :set , :fail , :complete
67
63
68
- def work
69
- sleep_until_scheduled_time
64
+ private
70
65
66
+ def do_work
71
67
if compare_and_set_state ( :in_progress , :pending )
72
68
success , val , reason = SafeTaskExecutor . new ( @task ) . execute
73
69
@@ -79,14 +75,19 @@ def work
79
75
time = Time . now
80
76
observers . notify_and_delete_observers { [ time , self . value , reason ] }
81
77
end
82
-
83
78
end
84
79
85
- private
80
+ def do_next_interval
81
+ return if cancelled?
82
+
83
+ interval = mutex . synchronize do
84
+ [ 60 , [ ( @schedule_time . to_f - Time . now . to_f ) , 0 ] . max ] . min
85
+ end
86
86
87
- def sleep_until_scheduled_time
88
- while ( diff = @schedule_time . to_f - Time . now . to_f ) > 0
89
- sleep ( diff > 60 ? 60 : diff )
87
+ if interval > 0
88
+ Concurrent ::timer ( interval , &method ( :do_next_interval ) )
89
+ else
90
+ do_work
90
91
end
91
92
end
92
93
0 commit comments