Skip to content

RunLoop

A RunLoop is a queue of blocks and the thread that runs them. Any thread can post to it. The blocks run in order on the thread that calls run.

#import "RunLoop.xc"
RunLoop* main = RunLoop.main();
main.post(block void(void) { … }); // from any thread
main.after((u32)500, block void(void) { … }); // once, in 500 ms
Timer* t = main.every((u32)1000, block void(void) { … }); // until t.cancel()
main.run(); // until main.stop()

This is how work done on another thread gets back to the main one. Http and AsyncFiles normally call their completion blocks on their own worker threads. After deliverOn(RunLoop.main()) they post them here instead:

Http.deliverOn(RunLoop.main());
Http.fetch(url, block void(u32 status, String* body) {
// runs on the thread that calls RunLoop.main().run()
});
RunLoop.main().run();

run blocks until stop. A program that already has a loop of its own, such as a UI toolkit’s frame callback, calls runPending from it instead. That runs whatever is queued and returns.

Timers are checked once per jiffy (1/60 s), so a timer can fire up to about 17 ms late. They use the host’s monotonic clock, so changing the wall clock does not move them.

static RunLoop* main(void)

The process’s main run loop, created on first use. Make the first call from one thread, before other threads use it.

void post(block work void(void))

Queues work to run on the loop’s thread. Any thread may call it. Blocks run in the order they were posted.

void run(void)

Runs posted blocks and timers on the calling thread until stop is called.

u32 runPending(void)

Runs every block queued at the time of the call and returns how many ran. It does not wait for more.

void stop(void)

Makes run return after the block it is running. Any thread may call it. If no run is in progress, the next one returns at once.

Timer* after(u32 ms, block work void(void))

Runs work once, ms milliseconds from now, on the loop’s thread.

Timer* every(u32 ms, block work void(void))

Runs work every ms milliseconds, starting ms from now, until the timer is cancelled. If the loop falls behind, the missed ticks are skipped, not run back to back.

void cancel(void)

Stops the timer. A tick that is already queued does not run. Any thread may call it.

bool isCancelled(void)

Whether cancel has been called.