@@ -242,19 +242,14 @@ object Dispatcher {
242242 states
243243 })
244244 ec <- Resource .eval(F .executionContext)
245- alive <- Resource .make(F .delay(new AtomicBoolean (true )))(ref => F .delay(ref.set(false )))
246245
247246 // supervisor for the main loop, which needs to always restart unless the Supervisor itself is canceled
248247 // critically, inner actions can be canceled without impacting the loop itself
249248 supervisor <- Supervisor [F ](await, Some ((_ : Outcome [F , Throwable , _]) => true ))
250249
251250 _ <- {
252- def dispatcher (
253- doneR : AtomicBoolean ,
254- latch : AtomicReference [() => Unit ],
255- state : Array [AtomicReference [List [Registration ]]]): F [Unit ] = {
256-
257- val step = for {
251+ def step (state : Array [AtomicReference [List [Registration ]]], await : F [Unit ]): F [Unit ] =
252+ for {
258253 regs <- F delay {
259254 val buffer = mutable.ListBuffer .empty[Registration ]
260255 var i = 0
@@ -271,12 +266,7 @@ object Dispatcher {
271266
272267 _ <-
273268 if (regs.isEmpty) {
274- F .async_[Unit ] { cb =>
275- if (! latch.compareAndSet(Noop , () => cb(Completed ))) {
276- // state was changed between when we last set the latch and now; complete the callback immediately
277- cb(Completed )
278- }
279- }
269+ await
280270 } else {
281271 regs traverse_ {
282272 case r @ Registration (action, prepareCancel) =>
@@ -289,10 +279,23 @@ object Dispatcher {
289279 }
290280 } yield ()
291281
282+ def dispatcher (
283+ doneR : AtomicBoolean ,
284+ latch : AtomicReference [() => Unit ],
285+ state : Array [AtomicReference [List [Registration ]]]): F [Unit ] = {
286+
287+ val await =
288+ F .async_[Unit ] { cb =>
289+ if (! latch.compareAndSet(Noop , () => cb(Completed ))) {
290+ // state was changed between when we last set the latch and now; complete the callback immediately
291+ cb(Completed )
292+ }
293+ }
294+
292295 F .delay(latch.set(Noop )) *> // reset latch
293296 // if we're marked as done, yield immediately to give other fibers a chance to shut us down
294297 // we might loop on this a few times since we're marked as done before the supervisor is canceled
295- F .delay(doneR.get()).ifM(F .cede, step)
298+ F .delay(doneR.get()).ifM(F .cede, step(state, await) )
296299 }
297300
298301 0 .until(workers).toList traverse_ { n =>
@@ -301,12 +304,15 @@ object Dispatcher {
301304 val worker = dispatcher(doneR, latch, states(n))
302305 val release = F .delay(latch.getAndSet(Open )())
303306 Resource .make(supervisor.supervise(worker)) { _ =>
304- // published by release
305- F .delay(doneR.lazySet(true )) *> release
307+ F .delay(doneR.set(true )) *> step(states(n), F .unit) *> release
306308 }
307309 }
308310 }
309311 }
312+
313+ // Alive is the innermost resource so that when releasing
314+ // the very first thing we do is set dispatcher to un-alive
315+ alive <- Resource .make(F .delay(new AtomicBoolean (true )))(ref => F .delay(ref.set(false )))
310316 } yield {
311317 new Dispatcher [F ] {
312318 override def unsafeRunAndForget [A ](fa : F [A ]): Unit = {
0 commit comments