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"Overview
Section titled “Overview”RunLoop* main = RunLoop.main();
main.post(block void(void) { … }); // from any threadmain.after(500, block void(void) { … }); // once, in 500 msTimer* t = main.every(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. If that loop sleeps until it has an event, it installs a
setWakeHook so that a post wakes it.
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.
RunLoop
Section titled “RunLoop”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.
runPending
Section titled “runPending”u32 runPending(void)Runs every block queued at the time of the call and returns how many ran. It does not wait for more.
setWakeHook
Section titled “setWakeHook”void setWakeHook(block hook void(void), bool hasHook)For a loop whose thread waits somewhere else, such as a UI toolkit’s event
loop that calls runPending each time round. After every
post, and every timer that fires, hook is called on the thread
that posted, outside the loop’s lock. It must be safe to call from any thread
and should only wake the waiting thread. hasHook false removes the hook.
RunLoop.main().setWakeHook(block void(void) { wakeTheEventLoop(); }, true);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.
cancel
Section titled “cancel”void cancel(void)Stops the timer. A tick that is already queued does not run. Any thread may call it.
isCancelled
Section titled “isCancelled”bool isCancelled(void)Whether cancel has been called.