# Idling

Dusk's "main" execution loop is to repeatedly fetch word from its input source
and execute it. If the input source is interactive, it means that it spends the
vast majority of its time waiting for this source.

This unit realiases "idle" in order to allow it to perform an arbitrary list
of tasks one after the other.

The idle word, which begins as a noop, can be grafted words with a ( -- )
signature. Whenever a word is grafted, through "idleadd", "idle" begins
executing it each time it's called.

Calling "idle" calls all grafted words in grafting order.

All units in Dusk needing to do some idling do so through this unit.

## "idle" is a core word

Above, we say "realiases" rather than "provide" because the word "idle" is
defined in core words because it is referenced early in the boot process.
However, this word is reserved for the semantics of the lib/idle unit. However,
you don't need to add "lib/idle" to your dependencies in order to call "idle".

## When to idle?

When writing code, sometimes it's appropriate to insert a "idle", but it's not
always clear when. The general guideline is that idling should happen every few
tens of milliseconds.

First of all, there's the run loops. Whenever you're in a loop that implies
interaction with the operator, you need to idle.

Although we could, if we wanted, idle at every mass storage access, or every
"f<<", we don't. It's too deep in granularity. Most of the time, such access is
instant from the perspective of the operator.

But sometimes, we know that some operations take longer than it should for the
operator to stay without feedback.

One such example is the test suite. It take several seconds to run. We can't
leave the operator without a idle loop. Therefore, we idle at "testbegin" and
"testend" in [tests/harness.fs].

Another example is Duskberon [oberon]. On a Raspberry Pi, it takes a few seconds
to load it all. It's a close call, but it's enough to pass the threshold.
Therefore, we add a idle call in the "Loading module" message in
[comp/oberon.fs].

Another obvious example is the booting sequence. For a while, we have no way to
output anything on the screen, but when we do, we appreciate the feedback.
Therefore, it's a good idea, on systems that don't have instant boot, to litter
theit init.fs file with ".." calls (see below).

One place *not* to call idle in is in low level drivers. When you do, it's
likely that you end up in a self-referential loop. When drivers need to wait,
they must use [drv/timer].

## Example usage


  needs lib/idle
  variable mycounter
  :> 1 mycounter +! ; idleadd
  ...
  mycounter @ . \ This number should be going up very fast

## API

idle ( -- )
  Call all words previously grafted through "idleadd" in added order.

idleadd ( xt -- )
  Add word "xt" , which must have the signature ( -- ), to the idle loop.

.. ( -- )
  Shortcut of "'.' emit idle". It's appropriate to use in long loading sequences
  to indicate progress. Using only "emit" doesn't cut it in some cases, such as
  [io/grid] systems, because those systems only refresh themselves on idling.
  Therefore, you'll want to use this word instead.
