Problem
Example/Common/ExampleServiceThread.c busy-spins:
while (!(*shutdown))
{
SolidSyslog_Service();
}
When the buffer is empty and the store has no unsent records, _Service returns instantly and the loop hammers the CPU at 100%. On Windows, this also contends with the producer for the buffer mutex on every iteration.
Discovered alongside #275 / S12.14 architecture work — orthogonal but worth fixing for production realism of the example code.
Scope
ExampleServiceThread_Run takes an injected SolidSyslogSleepFunction and sleeps 1 ms unconditionally after every SolidSyslog_Service() call.
- The
SolidSyslogSleepFunction typedef and the POSIX/Windows wirings (SolidSyslogPosixSleep, SolidSyslogWindowsSleep) already exist for the TLS handshake retry — reuse them, no #ifdef needed.
SolidSyslog_Service itself stays void — the library makes no attempt here to signal idle state. That is deliberately deferred (see Future work below).
- Cost: a 1 ms latency cap on every tick. Well below RFC 5424 timestamp precision.
- Benefit: CPU usage drops from 100% to <1% when idle; producer lock contention disappears under load.
Test impact
- Update
ExampleServiceThreadTest to inject a counting SleepFake that flips the shutdown flag after the first call — proves the sleep was invoked once per tick at the expected millisecond count.
- No core library tests change; the public API is unchanged.
Future work (out of scope for this story)
A later story can investigate signalling — making the service thread block until either a buffer write or a shutdown signal occurs, eliminating the 1 ms polling tick entirely. That would need cross-platform primitives (eventfd / SetEvent / RTOS task notifications) plumbed through the buffer abstraction and is a larger design effort. Keeping this story to a simple unconditional yield avoids committing to a particular signalling design now.
Notes
- Independent of S12.12 and S12.14.
- Library API surface is unchanged — this story lives entirely in
Example/Common/ and the per-platform mains.
Parent epic: #31
Problem
Example/Common/ExampleServiceThread.cbusy-spins:When the buffer is empty and the store has no unsent records,
_Servicereturns instantly and the loop hammers the CPU at 100%. On Windows, this also contends with the producer for the buffer mutex on every iteration.Discovered alongside #275 / S12.14 architecture work — orthogonal but worth fixing for production realism of the example code.
Scope
ExampleServiceThread_Runtakes an injectedSolidSyslogSleepFunctionand sleeps 1 ms unconditionally after everySolidSyslog_Service()call.SolidSyslogSleepFunctiontypedef and the POSIX/Windows wirings (SolidSyslogPosixSleep,SolidSyslogWindowsSleep) already exist for the TLS handshake retry — reuse them, no#ifdefneeded.SolidSyslog_Serviceitself staysvoid— the library makes no attempt here to signal idle state. That is deliberately deferred (see Future work below).Test impact
ExampleServiceThreadTestto inject a countingSleepFakethat flips the shutdown flag after the first call — proves the sleep was invoked once per tick at the expected millisecond count.Future work (out of scope for this story)
A later story can investigate signalling — making the service thread block until either a buffer write or a shutdown signal occurs, eliminating the 1 ms polling tick entirely. That would need cross-platform primitives (eventfd / SetEvent / RTOS task notifications) plumbed through the buffer abstraction and is a larger design effort. Keeping this story to a simple unconditional yield avoids committing to a particular signalling design now.
Notes
Example/Common/and the per-platform mains.Parent epic: #31