# Event Loop This guide gives an overview of how the event loop is implemented. ## Overview {ruby Async::Reactor} provides the event loop and sits at the root of any task tree. Work is scheduled by adding {ruby Async::Task} instances to the reactor. When you invoke {ruby Async::Reactor#async}, the parent task is determined by calling {ruby Async::Task.current?} which uses fiber local storage. A slightly more efficient method is to use {ruby Async::Task#async}, which uses {ruby self} as the parent task. ~~~ ruby require 'async' def sleepy(duration, task: Async::Task.current) task.async do |subtask| subtask.annotate "I'm going to sleep #{duration}s..." subtask.sleep duration puts "I'm done sleeping!" end end def nested_sleepy(task: Async::Task.current) task.async do |subtask| subtask.annotate "Invoking sleepy 5 times..." 5.times do |index| sleepy(index, task: subtask) end end end Async do |task| task.annotate "Invoking nested_sleepy..." subtask = nested_sleepy # Print out all running tasks in a tree: task.print_hierarchy($stderr) # Kill the subtask subtask.stop end ~~~ ### Thread Safety Most methods of the reactor and related tasks are not thread-safe, so you'd typically have [one reactor per thread or process](https://github.com/socketry/async-container). ### Embedding Reactors {ruby Async::Scheduler#run} will run until the reactor runs out of work to do. To run a single iteration of the reactor, use {ruby Async::Scheduler#run_once} ~~~ ruby require 'async' Console.logger.debug! reactor = Async::Reactor.new # Run the reactor for 1 second: reactor.async do |task| task.sleep 1 puts "Finished!" end while reactor.run_once # Round and round we go! end ~~~ You can use this approach to embed the reactor in another event loop. For some integrations, you may want to specify the maximum time to wait to {ruby Async::Scheduler#run_once}. ### Stopping Reactors {ruby Async::Reactor#stop} will stop the current reactor and all children tasks. ### Interrupting Reactors {ruby Async::Reactor#interrupt} can be called safely from a different thread (or signal handler) and will cause the reactor to exit with an {ruby Interrupt} exception.