7. Execution model

7.1 Two clocks

Clock Drives Used by
Simulated behaviour: delays, timeouts, after, time.Every, time.Now node and main context
Presentation the screen: tweens, after inside observers look context

A handler's after uses the clock of the context it runs in. The simulated clock has microsecond resolution.

7.2 The event loop

The simulator keeps one queue of pending events ordered by (simulated time, sequence number). The sequence number increases with every insertion, so events at the same time run in the order they were scheduled. One step is:

  1. Pop the first event.
  2. Run it to completion (handlers never interleave).
  3. Append the trace events it produced.
  4. Evaluate every active always.

The run ends when the queue is empty (sim.Ended reason "empty", at the time of the last step) or when the next event is later than sim.StopAt (reason "stop", at sim.StopAt). Events at exactly sim.StopAt run. An event later than 10 minutes of simulated time (and than sim.StopAt, if set) fails the run with time-limit at 10 minutes.

Order at time 0

  1. define main runs to completion and its after blocks are scheduled. A node created in main (or later) gets the initial Node has state of every package it runs immediately, so main can adjust it (set server.tcp.State to "LISTEN"), and a start event is queued for it.
  2. Each node's start event runs the define [n: Node] start of every package the node runs that has one, in dependency order, with the receiver bound to the node (one step per node, in creation order).

7.3 Node events

Taught in 5. Messages

7.4 Timers

Taught in 3. Time

after d schedules its block at now + d in the same context: on the receiver's node in node context, or in main. In a phrase without a receiver that several contexts share (time.Every), it schedules on the node of the running event, or in main. A negative delay is a bad-argument error. The block captures the values of locals and bound names, the receiver included, at scheduling time. Fields read through the receiver (n.Heartbeat) are read live when it runs. Because the block holds copies, setting a local captured from outside it is a bad-place error, and result inside it is a context error. There is no timer cancellation: check a condition when the timer fires instead.

7.5 Crash and restart

7.6 The network

Configured from main with std/net (see std/README.md):

7.7 Determinism

7.8 Run-time errors

A run-time error (missing key, type mismatch, division by zero, sending to sim.Nobody…) stops the run and is recorded as the last trace event sim.Failed with the error code, message and source location. The location is in user code: an error raised inside std is placed at the call that entered std (spec/11 §11.3). There is no sim.Ended after it. Everything up to it can still be played. Codes: spec/11 §11.3.