diff --git a/src/crystal/event_loop.cr b/src/crystal/event_loop.cr index fb7ab98bfa3a..424e8f2c2312 100644 --- a/src/crystal/event_loop.cr +++ b/src/crystal/event_loop.cr @@ -69,6 +69,13 @@ abstract class Crystal::EventLoop abstract def run(queue : Fiber::List*, blocking : Bool) : Nil {% end %} + # Blocks the current scheduler until all the pending events have completed. + # Must yield every runnable fiber. + # + # Optional. + def drain(& : Fiber ->) : Nil + end + # Tells a blocking run loop to no longer wait for events to activate. It may # for example enqueue a NOOP event with an immediate (or past) timeout. Having # activated an event, the loop shall return, allowing the blocked thread to diff --git a/src/fiber/execution_context/parallel/scheduler.cr b/src/fiber/execution_context/parallel/scheduler.cr index d19fde08a07e..6e15de8d36ac 100644 --- a/src/fiber/execution_context/parallel/scheduler.cr +++ b/src/fiber/execution_context/parallel/scheduler.cr @@ -130,7 +130,10 @@ module Fiber::ExecutionContext loop do if @shutdown spin_stop + + # drain everything into the global queue @runnables.drain + @event_loop.drain { |fiber| @global_queue.push(fiber) } # we may have been the last running scheduler, waiting on the event # loop while there are pending events for example; let's resume a