17
17
18
18
import java .util .PriorityQueue ;
19
19
import java .util .concurrent .TimeUnit ;
20
- import java .util .concurrent .atomic .AtomicInteger ;
20
+ import java .util .concurrent .atomic .AtomicLong ;
21
21
22
22
import rx .Scheduler ;
23
23
import rx .Subscription ;
24
+ import rx .subscriptions .CompositeSubscription ;
25
+ import rx .subscriptions .MultipleAssignmentSubscription ;
24
26
import rx .util .functions .Func2 ;
25
27
26
28
/**
27
29
* Schedules work on the current thread but does not execute immediately. Work is put in a queue and executed after the current unit of work is completed.
28
30
*/
29
31
public class CurrentThreadScheduler extends Scheduler {
30
32
private static final CurrentThreadScheduler INSTANCE = new CurrentThreadScheduler ();
33
+ private static final AtomicLong counter = new AtomicLong (0 );
31
34
32
35
public static CurrentThreadScheduler getInstance () {
33
36
return INSTANCE ;
@@ -38,25 +41,27 @@ public static CurrentThreadScheduler getInstance() {
38
41
/* package accessible for unit tests */ CurrentThreadScheduler () {
39
42
}
40
43
41
- private final AtomicInteger counter = new AtomicInteger (0 );
42
-
43
44
@ Override
44
45
public <T > Subscription schedule (T state , Func2 <? super Scheduler , ? super T , ? extends Subscription > action ) {
46
+ // immediately move to the InnerCurrentThreadScheduler
47
+ InnerCurrentThreadScheduler innerScheduler = new InnerCurrentThreadScheduler ();
45
48
DiscardableAction <T > discardableAction = new DiscardableAction <T >(state , action );
46
- enqueue (discardableAction , now ());
47
- return discardableAction ;
49
+ enqueue (innerScheduler , discardableAction , now ());
50
+ return innerScheduler ;
48
51
}
49
52
50
53
@ Override
51
54
public <T > Subscription schedule (T state , Func2 <? super Scheduler , ? super T , ? extends Subscription > action , long dueTime , TimeUnit unit ) {
52
55
long execTime = now () + unit .toMillis (dueTime );
53
56
57
+ // immediately move to the InnerCurrentThreadScheduler
58
+ InnerCurrentThreadScheduler innerScheduler = new InnerCurrentThreadScheduler ();
54
59
DiscardableAction <T > discardableAction = new DiscardableAction <T >(state , new SleepingAction <T >(action , this , execTime ));
55
- enqueue (discardableAction , execTime );
60
+ enqueue (innerScheduler , discardableAction , execTime );
56
61
return discardableAction ;
57
62
}
58
63
59
- private void enqueue (DiscardableAction <?> action , long execTime ) {
64
+ private static void enqueue (Scheduler scheduler , DiscardableAction <?> action , long execTime ) {
60
65
PriorityQueue <TimedAction > queue = QUEUE .get ();
61
66
boolean exec = queue == null ;
62
67
@@ -69,19 +74,50 @@ private void enqueue(DiscardableAction<?> action, long execTime) {
69
74
70
75
if (exec ) {
71
76
while (!queue .isEmpty ()) {
72
- queue .poll ().action .call (this );
77
+ queue .poll ().action .call (scheduler );
73
78
}
74
79
75
80
QUEUE .set (null );
76
81
}
77
82
}
78
83
84
+ private static class InnerCurrentThreadScheduler extends Scheduler implements Subscription {
85
+ private final MultipleAssignmentSubscription childSubscription = new MultipleAssignmentSubscription ();
86
+
87
+ @ Override
88
+ public <T > Subscription schedule (T state , Func2 <? super Scheduler , ? super T , ? extends Subscription > action ) {
89
+ DiscardableAction <T > discardableAction = new DiscardableAction <T >(state , action );
90
+ childSubscription .set (discardableAction );
91
+ enqueue (this , discardableAction , now ());
92
+ return childSubscription ;
93
+ }
94
+
95
+ @ Override
96
+ public <T > Subscription schedule (T state , Func2 <? super Scheduler , ? super T , ? extends Subscription > action , long delayTime , TimeUnit unit ) {
97
+ long execTime = now () + unit .toMillis (delayTime );
98
+
99
+ DiscardableAction <T > discardableAction = new DiscardableAction <T >(state , action );
100
+ childSubscription .set (discardableAction );
101
+ enqueue (this , discardableAction , execTime );
102
+ return childSubscription ;
103
+ }
104
+
105
+ @ Override
106
+ public void unsubscribe () {
107
+ childSubscription .unsubscribe ();
108
+ }
109
+
110
+ }
111
+
112
+ /**
113
+ * Use time to sort items so delayed actions are sorted to their appropriate position in the queue.
114
+ */
79
115
private static class TimedAction implements Comparable <TimedAction > {
80
116
final DiscardableAction <?> action ;
81
117
final Long execTime ;
82
- final Integer count ; // In case if time between enqueueing took less than 1ms
118
+ final Long count ; // In case if time between enqueueing took less than 1ms
83
119
84
- private TimedAction (DiscardableAction <?> action , Long execTime , Integer count ) {
120
+ private TimedAction (DiscardableAction <?> action , Long execTime , Long count ) {
85
121
this .action = action ;
86
122
this .execTime = execTime ;
87
123
this .count = count ;
0 commit comments