Solution (source code)

= Solution

Maintain the latest five <temperature> readings in a <circular buffer>, together with their running <sum>. The following <C programming language> code spells out the <message passing> interface rather than assuming a particular library: `send(dst,&m)` is a blocking <synchronous message passing> send; `receive(src,&m)` receives from the specified sender or `ANY` and returns the sender's identity; `sendrec(dst,&m)` atomically sends the request and waits for that sender's reply in the same message object. Successful, reliable operations are assumed. Message contents are copied by the interface.

``
enum { ANY = -1, TIMER = 1, TEMP = 2 };
enum { PULSE, PING, REQUEST, REPLY };
typedef struct {
    int type;
    int period_ms;
    double value;
} Message;

extern void send(int dst, const Message *m);
extern int receive(int src, Message *m);
extern void sendrec(int dst, Message *m);

void smooth(void) {
    double history[5] = {0};
    double sum = 0;
    int count = 0, next = 0;
    Message m = { .type = PULSE, .period_ms = 1000 };
    send(TIMER, &m);                 /* subscribe once */

    for (;;) {
        int sender = receive(count < 5 ? TIMER : ANY, &m);
        if (sender == TIMER && m.type == PING) {
            Message t = { .type = REQUEST };
            sendrec(TEMP, &t);       /* matching REPLY contains t.value */
            if (count == 5)
                sum -= history[next];
            else
                ++count;
            history[next] = t.value;
            sum += t.value;
            next = (next + 1) % 5;
        } else if (count == 5 && m.type == REQUEST) {
            Message answer = { .type = REPLY, .value = sum / 5.0 };
            send(sender, &answer);
        }
    }
}
``

Before the fifth reading, selective reception from `TIMER` prevents premature client requests from being accepted. Such clients wait at their synchronous sends; they are not given a partial <arithmetic mean>. Thereafter the <operating-system process> receives both timer messages and client requests. Each accepted `PING` initiates one measurement; each accepted client request returns the <arithmetic mean> of the five most recently completed measurements, without initiating another measurement or changing the <circular buffer>.

The <loop invariant> is that `count` is the number of valid readings, capped at five, `sum` is their <sum>, and `next` is the next unused slot during startup or the oldest slot afterwards. Removing the overwritten reading and adding the new one preserves this <loop invariant>. Each update and reply uses $O(1)$ <time complexity> and $O(1)$ storage, since the window length is fixed. Under timely sensor replies, timer delivery and <process scheduling>, measurements are initiated once per second. The next parts explain failures of these timing assumptions; the code does not promise one-second sampling when the <sensor> itself cannot sustain it.