15
15
*/
16
16
package rx .internal .schedulers ;
17
17
18
+ import java .util .ArrayList ;
19
+ import java .util .List ;
18
20
import java .util .concurrent .Future ;
19
21
import java .util .concurrent .atomic .AtomicIntegerFieldUpdater ;
20
22
21
23
import rx .Subscription ;
24
+ import rx .exceptions .CompositeException ;
22
25
import rx .exceptions .OnErrorNotImplementedException ;
23
26
import rx .functions .Action0 ;
24
27
import rx .plugins .RxJavaPlugins ;
29
32
* {@code Subscriber} in respect of an {@code Observer}.
30
33
*/
31
34
public final class ScheduledAction implements Runnable , Subscription {
32
- final CompositeSubscription cancel ;
35
+ final Subscription [] cancel ;
36
+ volatile int count ;
33
37
final Action0 action ;
34
38
/** Set by the run() method to avoid self interrupting at the end of the run method. */
35
- volatile Thread runner ;
39
+ Thread runner ;
36
40
37
41
public ScheduledAction (Action0 action ) {
38
42
this .action = action ;
39
- this .cancel = new CompositeSubscription () ;
43
+ this .cancel = new Subscription [ 4 ] ;
40
44
}
41
45
42
46
@ Override
43
47
public void run () {
48
+ Thread thread = Thread .currentThread ();
44
49
try {
45
- runner = Thread . currentThread () ;
50
+ runner = thread ;
46
51
action .call ();
47
52
} catch (Throwable e ) {
48
53
// nothing to do but print a System error as this is fatal and there is nowhere else to throw this
@@ -53,7 +58,6 @@ public void run() {
53
58
ie = new IllegalStateException ("Fatal Exception thrown on Scheduler.Worker thread." , e );
54
59
}
55
60
RxJavaPlugins .getInstance ().getErrorHandler ().handleError (ie );
56
- Thread thread = Thread .currentThread ();
57
61
thread .getUncaughtExceptionHandler ().uncaughtException (thread , ie );
58
62
} finally {
59
63
unsubscribe ();
@@ -62,22 +66,76 @@ public void run() {
62
66
63
67
@ Override
64
68
public boolean isUnsubscribed () {
65
- return cancel . isUnsubscribed () ;
69
+ return count < 0 ;
66
70
}
67
71
68
72
@ Override
69
73
public void unsubscribe () {
70
- cancel .unsubscribe ();
74
+ Subscription [] subs = cancel ;
75
+ if (count >= 0 ) {
76
+ synchronized (this ) {
77
+ if (count < 0 ) {
78
+ return ;
79
+ }
80
+ count = -1 ;
81
+ }
82
+ }
83
+ unsubscribeFromAll (subs );
71
84
}
72
85
86
+
73
87
/**
74
88
* Adds a general Subscription to this {@code ScheduledAction} that will be unsubscribed
75
89
* if the underlying {@code action} completes or the this scheduled action is cancelled.
76
90
*
77
91
* @param s the Subscription to add
78
92
*/
79
93
public void add (Subscription s ) {
80
- cancel .add (s );
94
+ if (count >= 0 ) {
95
+ synchronized (this ) {
96
+ int c = count ;
97
+ if (c >= 0 ) {
98
+ cancel [c ] = s ;
99
+ count = c + 1 ;
100
+ return ;
101
+ }
102
+ }
103
+ }
104
+ s .unsubscribe ();
105
+ }
106
+
107
+ private static void unsubscribeFromAll (Subscription ... subscriptions ) {
108
+ if (subscriptions == null ) {
109
+ return ;
110
+ }
111
+ List <Throwable > es = null ;
112
+ for (Subscription s : subscriptions ) {
113
+ if (s == null ) {
114
+ break ;
115
+ }
116
+ try {
117
+ s .unsubscribe ();
118
+ } catch (Throwable e ) {
119
+ if (es == null ) {
120
+ es = new ArrayList <Throwable >();
121
+ }
122
+ es .add (e );
123
+ }
124
+ }
125
+ if (es != null ) {
126
+ if (es .size () == 1 ) {
127
+ Throwable t = es .get (0 );
128
+ if (t instanceof RuntimeException ) {
129
+ throw (RuntimeException ) t ;
130
+ } else {
131
+ throw new CompositeException (
132
+ "Failed to unsubscribe to 1 or more subscriptions." , es );
133
+ }
134
+ } else {
135
+ throw new CompositeException (
136
+ "Failed to unsubscribe to 2 or more subscriptions." , es );
137
+ }
138
+ }
81
139
}
82
140
83
141
/**
@@ -86,7 +144,7 @@ public void add(Subscription s) {
86
144
* @param f the future to add
87
145
*/
88
146
public void add (final Future <?> f ) {
89
- cancel . add (new FutureCompleter (f ));
147
+ add (new FutureCompleter (f ));
90
148
}
91
149
92
150
/**
@@ -97,7 +155,7 @@ public void add(final Future<?> f) {
97
155
* the parent {@code CompositeSubscription} to add
98
156
*/
99
157
public void addParent (CompositeSubscription parent ) {
100
- cancel . add (new Remover (this , parent ));
158
+ add (new Remover (this , parent ));
101
159
}
102
160
103
161
/**
0 commit comments