## 10.3 Time

The module `Time` contains procedures for real-time applications.

`Alarm`

  > `{Time.alarm` `+I``` `?U``}`

  returns `unit` after `I` milliseconds. This is done asynchronously in that it is evaluated on its own thread.

`Delay`

  > `{Time.delay` `+I``}`

  reduces to `skip` after `I` milliseconds. Whenever `I``=< 0`, `{Delay` `I``}` reduces immediately.

`time`

  > `{Time.time` `?T``}`

  binds `T` to the number of seconds elapsed since January, 1st of the current year.

### The Repeater Class

`repeat`

  > `Time.repeat`

  is a class which allows to

  - repeat an action infinitely often, or a fixed number of times and perform some final action thereafter,

  - with a fixed delay between iterations (or, alternatively, a delay specified by a unary procedure),

  - stop and resume the iteration.

  There are default values for any of the iteration parameters. These are set on creation of an object inheriting from `Time.repeat` and can be changed by inheritance. The functionality is controlled by the following methods.

  `setRepAll`

    > > `setRepAll(action:` `+ActionPR``<= dummyRep
    > > final:` `+FinalPR``<= finalRep
    > > delay:` `+DelayI``<= 1000
    > > delayFun:` `+DelayFunP``<= fun {$} 1000 end
    > > number:` `+NumI``<= ~1)`

    initializes the loop with the action `ActionPR` to iterate (default: message `dummyRep`), the action `FinalPR` to finalize a finite iteration (default: message `finalRep`), the delay `DelayI` between iterations (default: one second), the function `DelayFunP` yielding the delay between iterations (default: constant `1000`), and the maximal number `NumI` of iterations (default: infinitely many).

    The methods `dummyRep` and `finalRep` do nothing. Only one of the `delay` and `delayFun` parameters can be given. The default actions `ActionPR` and `FinalPR` can be changed by inheritance.

    The loop is started on the calling thread.

    For example, try the following:

    > `local
    > O = {New Time.repeat
    > setRepAll(action: proc {$} {OS.system 'fortune' _} end
    > number: 10)}
    > in
    > {O go()}
    > end`

  `getRep`

    > > `getRep(action:` `?ActionPR``<= _
    > > final:` `?FinalPR``<= _
    > > delay:` `?DelayI``<= _
    > > delayFun:` `?DelayFunP``<= _
    > > number:` `?LimitI``<= _
    > > actual:` `?NumI``<= _)`

    returns the current loop parameters: `LimitI` returns the current limit of the iteration, and `NumI` the number of iterations left to be done. If the delay was specified via `DelayFunP` (which need not be constant), then `DelayI` returns the last delay used. If `DelayI` is requested before the start of the iteration, then `~1` is returned. The other values correspond to the fields of the method `setRepAll`.

    For example try:

    > `local
    > class Counter from Time.repeat
    > attr a: 0
    > meth inc() a := @a + 1 end
    > meth get(?A) A = @a end
    > meth finalRep() a := 0 end
    > end
    > C = {New Counter setRepAll(action: inc number: 1000)}
    > in
    > thread {C go()} end
    > {C getRep(final: {Browse}
    > action: {Browse}
    > actual: {Browse})}
    > {C get({Browse})}
    > end`

    This will show the atoms `'finalRep'` and `'inc'` in the Browser, as well as a number between `1` and `1000`. After termination of the loop, the value of `@a` will be reset to `0`.

  `setRepDelay`

    > `setRepDelay(``+DelayI``<= 1000}`

  `setRepNum`

    > `setRepNum(``+NumI``<= ~1)}`

  `setRepAction`

    > `setRepAction(``+ActionPR``<= dummyRep)`

  `setRepFinal`

    > `setRepFinal(``+FinalPR``<= finalRep)}`

  `setRepDelayFun`

    > `setRepDelayFun(``+DelayFunP``<= fun {$} 1000 end)`

    allow to set the numeric parameters of the iteration.

    `DelayI` and `NumI` must be integers. The iteration limit `NumI` is stored and subsequent loop instances (triggered by `go`) also obey it, unless the limit is reset to `~1`.

    `ActionPR` and `FinalPR` may be nullary procedures or records. If they are procedures they are called as is. If they are records, they are interpreted as messages to be sent to `self`.

    `DelayFunP` must be a unary procedure which returns an integer value on application.

  `go`

    > `go()`

    starts the loop if it is not currently running.

  `stop`

    > `stop()`

    halts the loop and resets the iteration index. The loop may be restarted with `go`.