Problem
The library tells integrators to drive SolidSyslog_Service() from a permanent loop with a fixed delay. That works but is wasteful: on an idle system it burns CPU/power polling for nothing, and on a backlog it sleeps between units of work when it should be cycling. Service() returns void, so the host has no way to know whether there is more to do, whether it should back off, or whether the store has wedged — it can only guess with a timer.
Everything the host needs to make that decision already exists inside Service(): the buffer drain knows whether it moved anything, the send step knows whether it failed, and the store knows whether it has unsent records and whether it is halted. We just throw that knowledge away by returning void.
Approach
Surface that state as a return value and let the integrator build whatever wake/sleep mechanism their OS offers — semaphore, task notification, auto-reset event, or plain sleep — in a thin wrapper around Log and Service. The library stays fully OS-agnostic: no new injected primitive, no vtable, no per-platform code. The entire change is Service()'s return type.
The host's loop becomes:
for (;;) {
switch (SolidSyslog_Service(h)) {
case SOLIDSYSLOG_SERVICE_READY: break; /* loop now */
case SOLIDSYSLOG_SERVICE_IDLE: wait_for_log_signal(); /* until next Log */
case SOLIDSYSLOG_SERVICE_BLOCKED: wait_with_backoff(); /* sender down */
case SOLIDSYSLOG_SERVICE_HALTED: handle_halt(); /* store wedged */
}
}
Wake-on-Log is the integrator's wrapper signalling their own primitive right after SolidSyslog_Log() — the library never holds an OS handle. The status is purely an advisory wakeup hint; correctness comes from Service re-deriving state from the real buffer/store each call, so a missed or spurious signal is always safe.
Out of scope
- Any OS-specific waitable/semaphore in the library.
- Worked per-platform wrapper examples and prose — the upcoming documentation epic rewrites that material; this epic only documents the contract in the
Service() header comment.
- The latent "a
HALTED store never drains itself even when the sender recovers" behaviour — separate fix if we decide it is wrong.
Stories
- S31.01 —
Service returns a four-state servicing status (IDLE / READY / BLOCKED / HALTED).
Problem
The library tells integrators to drive
SolidSyslog_Service()from a permanent loop with a fixed delay. That works but is wasteful: on an idle system it burns CPU/power polling for nothing, and on a backlog it sleeps between units of work when it should be cycling.Service()returnsvoid, so the host has no way to know whether there is more to do, whether it should back off, or whether the store has wedged — it can only guess with a timer.Everything the host needs to make that decision already exists inside
Service(): the buffer drain knows whether it moved anything, the send step knows whether it failed, and the store knows whether it has unsent records and whether it is halted. We just throw that knowledge away by returningvoid.Approach
Surface that state as a return value and let the integrator build whatever wake/sleep mechanism their OS offers — semaphore, task notification, auto-reset event, or plain sleep — in a thin wrapper around
LogandService. The library stays fully OS-agnostic: no new injected primitive, no vtable, no per-platform code. The entire change isService()'s return type.The host's loop becomes:
Wake-on-
Logis the integrator's wrapper signalling their own primitive right afterSolidSyslog_Log()— the library never holds an OS handle. The status is purely an advisory wakeup hint; correctness comes fromServicere-deriving state from the real buffer/store each call, so a missed or spurious signal is always safe.Out of scope
Service()header comment.HALTEDstore never drains itself even when the sender recovers" behaviour — separate fix if we decide it is wrong.Stories
Servicereturns a four-state servicing status (IDLE/READY/BLOCKED/HALTED).