1616package rx .internal .schedulers ;
1717
1818import java .util .concurrent .*;
19+ import java .util .concurrent .atomic .AtomicReference ;
1920
2021import rx .*;
2122import rx .functions .Action0 ;
2223import rx .internal .util .*;
2324import rx .subscriptions .*;
2425
25- public class EventLoopsScheduler extends Scheduler {
26+ public class EventLoopsScheduler extends Scheduler implements SchedulerLifecycle {
2627 /** Manages a fixed number of workers. */
2728 private static final String THREAD_NAME_PREFIX = "RxComputationThreadPool-" ;
2829 private static final RxThreadFactory THREAD_FACTORY = new RxThreadFactory (THREAD_NAME_PREFIX );
@@ -44,40 +45,82 @@ public class EventLoopsScheduler extends Scheduler {
4445 }
4546 MAX_THREADS = max ;
4647 }
48+
49+ static final PoolWorker SHUTDOWN_WORKER ;
50+ static {
51+ SHUTDOWN_WORKER = new PoolWorker (new RxThreadFactory ("RxComputationShutdown-" ));
52+ SHUTDOWN_WORKER .unsubscribe ();
53+ }
54+
4755 static final class FixedSchedulerPool {
4856 final int cores ;
4957
5058 final PoolWorker [] eventLoops ;
5159 long n ;
5260
53- FixedSchedulerPool () {
61+ FixedSchedulerPool (int maxThreads ) {
5462 // initialize event loops
55- this .cores = MAX_THREADS ;
56- this .eventLoops = new PoolWorker [cores ];
57- for (int i = 0 ; i < cores ; i ++) {
63+ this .cores = maxThreads ;
64+ this .eventLoops = new PoolWorker [maxThreads ];
65+ for (int i = 0 ; i < maxThreads ; i ++) {
5866 this .eventLoops [i ] = new PoolWorker (THREAD_FACTORY );
5967 }
6068 }
6169
6270 public PoolWorker getEventLoop () {
71+ int c = cores ;
72+ if (c == 0 ) {
73+ return SHUTDOWN_WORKER ;
74+ }
6375 // simple round robin, improvements to come
64- return eventLoops [(int )(n ++ % cores )];
76+ return eventLoops [(int )(n ++ % c )];
77+ }
78+
79+ public void shutdown () {
80+ for (PoolWorker w : eventLoops ) {
81+ w .unsubscribe ();
82+ }
6583 }
6684 }
85+ /** This will indicate no pool is active. */
86+ static final FixedSchedulerPool NONE = new FixedSchedulerPool (0 );
6787
68- final FixedSchedulerPool pool ;
88+ final AtomicReference < FixedSchedulerPool > pool ;
6989
7090 /**
7191 * Create a scheduler with pool size equal to the available processor
7292 * count and using least-recent worker selection policy.
7393 */
7494 public EventLoopsScheduler () {
75- pool = new FixedSchedulerPool ();
95+ this .pool = new AtomicReference <FixedSchedulerPool >(NONE );
96+ start ();
7697 }
7798
7899 @ Override
79100 public Worker createWorker () {
80- return new EventLoopWorker (pool .getEventLoop ());
101+ return new EventLoopWorker (pool .get ().getEventLoop ());
102+ }
103+
104+ @ Override
105+ public void start () {
106+ FixedSchedulerPool update = new FixedSchedulerPool (MAX_THREADS );
107+ if (!pool .compareAndSet (NONE , update )) {
108+ update .shutdown ();
109+ }
110+ }
111+
112+ @ Override
113+ public void shutdown () {
114+ for (;;) {
115+ FixedSchedulerPool curr = pool .get ();
116+ if (curr == NONE ) {
117+ return ;
118+ }
119+ if (pool .compareAndSet (curr , NONE )) {
120+ curr .shutdown ();
121+ return ;
122+ }
123+ }
81124 }
82125
83126 /**
@@ -87,7 +130,7 @@ public Worker createWorker() {
87130 * @return the subscription
88131 */
89132 public Subscription scheduleDirect (Action0 action ) {
90- PoolWorker pw = pool .getEventLoop ();
133+ PoolWorker pw = pool .get (). getEventLoop ();
91134 return pw .scheduleActual (action , -1 , TimeUnit .NANOSECONDS );
92135 }
93136
@@ -137,4 +180,4 @@ private static final class PoolWorker extends NewThreadWorker {
137180 super (threadFactory );
138181 }
139182 }
140- }
183+ }
0 commit comments