1717
1818package monix .execution .schedulers
1919
20- import java .util .concurrent .{ExecutorService , ForkJoinPool , ScheduledExecutorService }
2120import monix .execution .internal .forkJoin .{AdaptedForkJoinPool , DynamicWorkerThreadFactory , StandardWorkerThreadFactory }
2221import monix .execution .internal .{InterceptRunnable , Platform , ScheduledExecutors }
23- import monix .execution .{Cancelable , UncaughtExceptionReporter }
24- import monix .execution .{Features , Scheduler }
22+ import monix .execution .{Cancelable , Features , Scheduler , UncaughtExceptionReporter }
23+
24+ import java .util .concurrent .{ExecutorService , ScheduledExecutorService }
2525// Prevents conflict with the deprecated symbol
2626import monix .execution .{ExecutionModel => ExecModel }
27- import scala . concurrent .{ ExecutionContext , Future , Promise , blocking }
27+
2828import scala .concurrent .duration .TimeUnit
29+ import scala .concurrent .{ExecutionContext , Future , Promise , blocking }
2930import scala .util .control .NonFatal
3031
3132/** An [[ExecutorScheduler ]] is a class for building a
@@ -54,9 +55,10 @@ abstract class ExecutorScheduler(e: ExecutorService, r: UncaughtExceptionReporte
5455 awaitOn.execute(new Runnable {
5556 override def run () =
5657 try blocking {
57- p.success(e.awaitTermination(timeout, unit))
58- ()
59- } catch {
58+ p.success(e.awaitTermination(timeout, unit))
59+ ()
60+ }
61+ catch {
6062 case ex if NonFatal (ex) =>
6163 p.failure(ex); ()
6264 }
@@ -78,10 +80,9 @@ abstract class ExecutorScheduler(e: ExecutorService, r: UncaughtExceptionReporte
7880}
7981
8082object ExecutorScheduler {
81- /** Builder for an [[ExecutorScheduler ]], converting a
82- * Java `ScheduledExecutorService`.
83+ /** Builder for an [[ExecutorScheduler ]], converting a Java `ExecutorService`.
8384 *
84- * @param service is the Java `ScheduledExecutorService ` that will take
85+ * @param service is the Java `ExecutorService ` that will take
8586 * care of scheduling and execution of all runnables.
8687 * @param reporter is the [[UncaughtExceptionReporter ]] that logs uncaught exceptions.
8788 * @param executionModel is the preferred
@@ -91,22 +92,58 @@ object ExecutorScheduler {
9192 * provided `ExecutorService` implements, see the documentation
9293 * for [[monix.execution.Scheduler.features Scheduler.features ]]
9394 */
95+ @ deprecated(" Use ExecutorScheduler.fromExecutorService" , " 3.4.2-avs.6" )
9496 def apply (
9597 service : ExecutorService ,
9698 reporter : UncaughtExceptionReporter ,
9799 executionModel : ExecModel ,
98- features : Features ): ExecutorScheduler = {
99-
100- // Implementations will inherit BatchingScheduler, so this is guaranteed
101- val ft = features + Scheduler .BATCHING
100+ features : Features ,
101+ ): ExecutorScheduler =
102102 service match {
103- case ref : ScheduledExecutorService =>
104- new FromScheduledExecutor (ref, reporter, executionModel, ft)
105- case _ =>
106- val s = Defaults .scheduledExecutor
107- new FromSimpleExecutor (s, service, reporter, executionModel, ft)
103+ case ref : AdaptedScheduledThreadPoolExecutor => scheduledThreadPool(ref, executionModel, features)
104+ case _ => fromExecutorService(service, reporter, executionModel, features)
108105 }
109- }
106+
107+ /** Builder for an [[ExecutorScheduler ]], converting a Java `ExecutorService`.
108+ *
109+ * @param service is the Java `ExecutorService` that will take
110+ * care of scheduling and execution of all runnables.
111+ * @param reporter is the [[UncaughtExceptionReporter ]] that logs uncaught exceptions.
112+ * @param executionModel is the preferred
113+ * [[monix.execution.ExecutionModel ExecutionModel ]], a guideline
114+ * for run-loops and producers of data.
115+ * @param features is the set of [[Features ]] that the
116+ * provided `ExecutorService` implements, see the documentation
117+ * for [[monix.execution.Scheduler.features Scheduler.features ]]
118+ */
119+ def fromExecutorService (
120+ service : ExecutorService ,
121+ reporter : UncaughtExceptionReporter ,
122+ executionModel : ExecModel ,
123+ features : Features ,
124+ ): ExecutorScheduler =
125+ new FromSimpleExecutor (
126+ scheduler = Defaults .scheduledExecutor,
127+ executor = service,
128+ reporter = reporter,
129+ executionModel = executionModel,
130+ features = withBatching(features)
131+ )
132+
133+ private [schedulers] def scheduledThreadPool (
134+ service : AdaptedScheduledThreadPoolExecutor ,
135+ executionModel : ExecModel ,
136+ features : Features ,
137+ ): ExecutorScheduler =
138+ new FromAdaptedThreadPoolExecutor (
139+ executor = service,
140+ executionModel = executionModel,
141+ features = withBatching(features)
142+ )
143+
144+ private def withBatching (features : Features ): Features =
145+ // Implementations will inherit BatchingScheduler, so this is guaranteed
146+ features + Scheduler .BATCHING
110147
111148 /**
112149 * DEPRECATED — provided for binary backwards compatibility.
@@ -117,9 +154,10 @@ object ExecutorScheduler {
117154 def apply (
118155 service : ExecutorService ,
119156 reporter : UncaughtExceptionReporter ,
120- executionModel : ExecModel ): ExecutorScheduler = {
157+ executionModel : ExecModel
158+ ): ExecutorScheduler = {
121159 // $COVERAGE-OFF$
122- apply (service, reporter, executionModel, Features .empty)
160+ fromExecutorService (service, reporter, executionModel, Features .empty)
123161 // $COVERAGE-ON$
124162 }
125163
@@ -131,7 +169,8 @@ object ExecutorScheduler {
131169 parallelism : Int ,
132170 daemonic : Boolean ,
133171 reporter : UncaughtExceptionReporter ,
134- executionModel : ExecModel ): ExecutorScheduler = {
172+ executionModel : ExecModel ,
173+ ): ExecutorScheduler = {
135174
136175 val handler = reporter.asJava
137176 val pool = new AdaptedForkJoinPool (
@@ -142,7 +181,7 @@ object ExecutorScheduler {
142181 asyncMode = true
143182 )
144183
145- apply (pool, reporter, executionModel, Features .empty)
184+ fromExecutorService (pool, reporter, executionModel, Features .empty)
146185 }
147186
148187 /** Creates an [[ExecutorScheduler ]] backed by a `ForkJoinPool`
@@ -154,7 +193,8 @@ object ExecutorScheduler {
154193 maxThreads : Int ,
155194 daemonic : Boolean ,
156195 reporter : UncaughtExceptionReporter ,
157- executionModel : ExecModel ): ExecutorScheduler = {
196+ executionModel : ExecModel ,
197+ ): ExecutorScheduler = {
158198
159199 val exceptionHandler = reporter.asJava
160200 val pool = new AdaptedForkJoinPool (
@@ -165,7 +205,7 @@ object ExecutorScheduler {
165205 asyncMode = true
166206 )
167207
168- apply (pool, reporter, executionModel, Features .empty)
208+ fromExecutorService (pool, reporter, executionModel, Features .empty)
169209 }
170210
171211 /** Converts a Java `ExecutorService`.
@@ -178,17 +218,18 @@ object ExecutorScheduler {
178218 private final class FromSimpleExecutor (
179219 scheduler : ScheduledExecutorService ,
180220 executor : ExecutorService ,
181- r : UncaughtExceptionReporter ,
221+ reporter : UncaughtExceptionReporter ,
182222 override val executionModel : ExecModel ,
183- override val features : Features )
184- extends ExecutorScheduler (executor, r ) {
223+ override val features : Features
224+ ) extends ExecutorScheduler (executor, reporter ) {
185225
186226 @ deprecated(" Provided for backwards compatibility" , " 3.0.0" )
187227 def this (
188228 scheduler : ScheduledExecutorService ,
189229 executor : ExecutorService ,
190230 r : UncaughtExceptionReporter ,
191- executionModel : ExecModel ) = {
231+ executionModel : ExecModel ,
232+ ) = {
192233 // $COVERAGE-OFF$
193234 this (scheduler, executor, r, executionModel, Features .empty)
194235 // $COVERAGE-ON$
@@ -198,53 +239,47 @@ object ExecutorScheduler {
198239 ScheduledExecutors .scheduleOnce(this , scheduler)(initialDelay, unit, r)
199240
200241 override def withExecutionModel (em : ExecModel ): SchedulerService =
201- new FromSimpleExecutor (scheduler, executor, r , em, features)
242+ new FromSimpleExecutor (scheduler, executor, reporter , em, features)
202243
203244 override def withUncaughtExceptionReporter (r : UncaughtExceptionReporter ): SchedulerService =
204245 new FromSimpleExecutor (scheduler, executor, r, executionModel, features)
205246 }
206247
207- /** Converts a Java `ScheduledExecutorService`. */
208- private final class FromScheduledExecutor (
209- s : ScheduledExecutorService ,
210- r : UncaughtExceptionReporter ,
248+ /** Implementation of ExecutorScheduler backed by Java `ScheduledExecutorService`. Assumes error reporting is done by
249+ * the underlying `ScheduledExecutorService`.
250+ *
251+ * Currently intended for use only with AdaptedThreadPoolExecutor.
252+ */
253+ private final class FromAdaptedThreadPoolExecutor (
254+ executor : AdaptedScheduledThreadPoolExecutor ,
211255 override val executionModel : ExecModel ,
212- override val features : Features )
213- extends ExecutorScheduler (s, r) {
214-
215- @ deprecated(" Provided for backwards compatibility" , " 3.0.0" )
216- def this (scheduler : ScheduledExecutorService , r : UncaughtExceptionReporter , executionModel : ExecModel ) = {
217- // $COVERAGE-OFF$
218- this (scheduler, r, executionModel, Features .empty)
219- // $COVERAGE-ON$
220- }
221-
222- override def executor : ScheduledExecutorService = s
256+ override val features : Features
257+ ) extends ExecutorScheduler (executor, null ) {
223258
224259 def scheduleOnce (initialDelay : Long , unit : TimeUnit , r : Runnable ): Cancelable = {
225260 if (initialDelay <= 0 ) {
226261 execute(r)
227262 Cancelable .empty
228263 } else {
229- val task = s .schedule(r, initialDelay, unit)
264+ val task = executor .schedule(r, initialDelay, unit)
230265 Cancelable (() => { task.cancel(true ); () })
231266 }
232267 }
233268
234269 override def scheduleWithFixedDelay (initialDelay : Long , delay : Long , unit : TimeUnit , r : Runnable ): Cancelable = {
235- val task = s .scheduleWithFixedDelay(r, initialDelay, delay, unit)
270+ val task = executor .scheduleWithFixedDelay(r, initialDelay, delay, unit)
236271 Cancelable (() => { task.cancel(false ); () })
237272 }
238273
239274 override def scheduleAtFixedRate (initialDelay : Long , period : Long , unit : TimeUnit , r : Runnable ): Cancelable = {
240- val task = s .scheduleAtFixedRate(r, initialDelay, period, unit)
275+ val task = executor .scheduleAtFixedRate(r, initialDelay, period, unit)
241276 Cancelable (() => { task.cancel(false ); () })
242277 }
243278
244279 override def withExecutionModel (em : ExecModel ): SchedulerService =
245- new FromScheduledExecutor (s, r , em, features)
280+ new FromAdaptedThreadPoolExecutor (executor , em, features)
246281
247282 override def withUncaughtExceptionReporter (r : UncaughtExceptionReporter ): SchedulerService =
248- new FromScheduledExecutor (s, r , executionModel, features)
283+ new FromAdaptedThreadPoolExecutor (executor.withUncaughtExceptionReporter(r) , executionModel, features)
249284 }
250285}
0 commit comments