17
17
18
18
import java .util .Date ;
19
19
import java .util .concurrent .TimeUnit ;
20
+ import java .util .concurrent .atomic .AtomicBoolean ;
20
21
21
22
import rx .subscriptions .Subscriptions ;
22
23
import rx .util .functions .Action0 ;
@@ -73,6 +74,8 @@ public abstract class Scheduler {
73
74
74
75
/**
75
76
* Schedules a cancelable action to be executed periodically.
77
+ * This default implementation schedules recursively and waits for actions to complete (instead of potentially executing
78
+ * long-running actions concurrently). Each scheduler that can do periodic scheduling in a better way should override this.
76
79
*
77
80
* @param state State to pass into the action.
78
81
* @param action The action to execute periodically.
@@ -81,7 +84,38 @@ public abstract class Scheduler {
81
84
* @param unit The time unit the interval above is given in.
82
85
* @return A subscription to be able to unsubscribe from action.
83
86
*/
84
- public abstract <T > Subscription schedulePeriodically (T state , Func2 <Scheduler , T , Subscription > action , long initialDelay , long period , TimeUnit unit );
87
+ public <T > Subscription schedulePeriodically (T state , final Func2 <Scheduler , T , Subscription > action , long initialDelay , long period , TimeUnit unit ) {
88
+ final long periodInNanos = unit .toNanos (period );
89
+ final AtomicBoolean complete = new AtomicBoolean ();
90
+
91
+ final Func2 <Scheduler , T , Subscription > recursiveAction = new Func2 <Scheduler , T , Subscription >() {
92
+ @ Override
93
+ public Subscription call (Scheduler scheduler , T state0 ) {
94
+ if (! complete .get ()) {
95
+ long startedAt = System .nanoTime ();
96
+ final Subscription sub1 = action .call (scheduler , state0 );
97
+ long timeTakenByActionInNanos = System .nanoTime () - startedAt ;
98
+ final Subscription sub2 = schedule (state0 , this , periodInNanos - timeTakenByActionInNanos , TimeUnit .NANOSECONDS );
99
+ return Subscriptions .create (new Action0 () {
100
+ @ Override
101
+ public void call () {
102
+ sub1 .unsubscribe ();
103
+ sub2 .unsubscribe ();
104
+ }
105
+ });
106
+ }
107
+ return Subscriptions .empty ();
108
+ }
109
+ };
110
+ final Subscription sub = schedule (state , recursiveAction , initialDelay , unit );
111
+ return Subscriptions .create (new Action0 () {
112
+ @ Override
113
+ public void call () {
114
+ complete .set (true );
115
+ sub .unsubscribe ();
116
+ }
117
+ });
118
+ }
85
119
86
120
/**
87
121
* Schedules a cancelable action to be executed at dueTime.
0 commit comments