Repository navigation
Expand file tree
/
Copy pathSchedulers.java
More file actions
240 lines (212 loc) · 7.89 KB
/
Copy pathSchedulers.java
File metadata and controls
240 lines (212 loc) · 7.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/**
* Copyright 2014 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package rx.schedulers;
import rx.Scheduler;
import rx.annotations.Experimental;
import rx.internal.schedulers.ExecutorScheduler;
import rx.internal.schedulers.GenericScheduledExecutorService;
import rx.internal.schedulers.SchedulerLifecycle;
import rx.internal.util.RxRingBuffer;
import rx.plugins.*;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
/**
* Static factory methods for creating Schedulers.
*/
public final class Schedulers {
private final Scheduler computationScheduler;
private final Scheduler ioScheduler;
private final Scheduler newThreadScheduler;
private static final AtomicReference<Schedulers> INSTANCE = new AtomicReference<Schedulers>();
private static Schedulers getInstance() {
for (;;) {
Schedulers current = INSTANCE.get();
if (current != null) {
return current;
}
current = new Schedulers();
if (INSTANCE.compareAndSet(null, current)) {
return current;
} else {
current.shutdownInstance();
}
}
}
private Schedulers() {
@SuppressWarnings("deprecation")
RxJavaSchedulersHook hook = RxJavaPlugins.getInstance().getSchedulersHook();
Scheduler c = hook.getComputationScheduler();
if (c != null) {
computationScheduler = c;
} else {
computationScheduler = RxJavaSchedulersHook.createComputationScheduler();
}
Scheduler io = hook.getIOScheduler();
if (io != null) {
ioScheduler = io;
} else {
ioScheduler = RxJavaSchedulersHook.createIoScheduler();
}
Scheduler nt = hook.getNewThreadScheduler();
if (nt != null) {
newThreadScheduler = nt;
} else {
newThreadScheduler = RxJavaSchedulersHook.createNewThreadScheduler();
}
}
/**
* Creates and returns a {@link Scheduler} that executes work immediately on the current thread.
*
* @return a {@link Scheduler} that executes work immediately
*/
public static Scheduler immediate() {
return rx.internal.schedulers.ImmediateScheduler.INSTANCE;
}
/**
* Creates and returns a {@link Scheduler} that queues work on the current thread to be executed after the
* current work completes.
*
* @return a {@link Scheduler} that queues work on the current thread
*/
public static Scheduler trampoline() {
return rx.internal.schedulers.TrampolineScheduler.INSTANCE;
}
/**
* Creates and returns a {@link Scheduler} that creates a new {@link Thread} for each unit of work.
* <p>
* Unhandled errors will be delivered to the scheduler Thread's {@link java.lang.Thread.UncaughtExceptionHandler}.
*
* @return a {@link Scheduler} that creates new threads
*/
public static Scheduler newThread() {
return RxJavaHooks.onNewThreadScheduler(getInstance().newThreadScheduler);
}
/**
* Creates and returns a {@link Scheduler} intended for computational work.
* <p>
* This can be used for event-loops, processing callbacks and other computational work.
* <p>
* Do not perform IO-bound work on this scheduler. Use {@link #io()} instead.
* <p>
* Unhandled errors will be delivered to the scheduler Thread's {@link java.lang.Thread.UncaughtExceptionHandler}.
*
* @return a {@link Scheduler} meant for computation-bound work
*/
public static Scheduler computation() {
return RxJavaHooks.onComputationScheduler(getInstance().computationScheduler);
}
/**
* Creates and returns a {@link Scheduler} intended for IO-bound work.
* <p>
* The implementation is backed by an {@link Executor} thread-pool that will grow as needed.
* <p>
* This can be used for asynchronously performing blocking IO.
* <p>
* Do not perform computational work on this scheduler. Use {@link #computation()} instead.
* <p>
* Unhandled errors will be delivered to the scheduler Thread's {@link java.lang.Thread.UncaughtExceptionHandler}.
*
* @return a {@link Scheduler} meant for IO-bound work
*/
public static Scheduler io() {
return RxJavaHooks.onIOScheduler(getInstance().ioScheduler);
}
/**
* Creates and returns a {@code TestScheduler}, which is useful for debugging. It allows you to test
* schedules of events by manually advancing the clock at whatever pace you choose.
*
* @return a {@code TestScheduler} meant for debugging
*/
public static TestScheduler test() { // NOPMD
return new TestScheduler();
}
/**
* Converts an {@link Executor} into a new Scheduler instance.
*
* @param executor
* the executor to wrap
* @return the new Scheduler wrapping the Executor
*/
public static Scheduler from(Executor executor) {
return new ExecutorScheduler(executor);
}
/**
* Resets the current {@link Schedulers} instance.
* This will re-init the cached schedulers on the next usage,
* which can be useful in testing.
*/
@Experimental
public static void reset() {
Schedulers s = INSTANCE.getAndSet(null);
if (s != null) {
s.shutdownInstance();
}
}
/**
* Starts those standard Schedulers which support the SchedulerLifecycle interface.
* <p>The operation is idempotent and threadsafe.
*/
public static void start() {
Schedulers s = getInstance();
s.startInstance();
synchronized (s) {
GenericScheduledExecutorService.INSTANCE.start();
RxRingBuffer.SPSC_POOL.start();
RxRingBuffer.SPMC_POOL.start();
}
}
/**
* Shuts down those standard Schedulers which support the SchedulerLifecycle interface.
* <p>The operation is idempotent and threadsafe.
*/
public static void shutdown() {
Schedulers s = getInstance();
s.shutdownInstance();
synchronized (s) {
GenericScheduledExecutorService.INSTANCE.shutdown();
RxRingBuffer.SPSC_POOL.shutdown();
RxRingBuffer.SPMC_POOL.shutdown();
}
}
/**
* Start the instance-specific schedulers.
*/
synchronized void startInstance() { // NOPMD
if (computationScheduler instanceof SchedulerLifecycle) {
((SchedulerLifecycle) computationScheduler).start();
}
if (ioScheduler instanceof SchedulerLifecycle) {
((SchedulerLifecycle) ioScheduler).start();
}
if (newThreadScheduler instanceof SchedulerLifecycle) {
((SchedulerLifecycle) newThreadScheduler).start();
}
}
/**
* Start the instance-specific schedulers.
*/
synchronized void shutdownInstance() { // NOPMD
if (computationScheduler instanceof SchedulerLifecycle) {
((SchedulerLifecycle) computationScheduler).shutdown();
}
if (ioScheduler instanceof SchedulerLifecycle) {
((SchedulerLifecycle) ioScheduler).shutdown();
}
if (newThreadScheduler instanceof SchedulerLifecycle) {
((SchedulerLifecycle) newThreadScheduler).shutdown();
}
}
}