diff --git a/src/metric.cpp b/src/metric.cpp index a0f9c2f..91cb853 100644 --- a/src/metric.cpp +++ b/src/metric.cpp @@ -379,8 +379,20 @@ struct Metric { Counter::Counter() = default; void Counter::inc(double x) { - // DESIGN: Single writer, but render thread reads concurrently - // Need atomic store since render thread reads without writer's coordination + // THREAD-SAFETY: This method mixes a non-atomic read and an atomic store + // which is safe ONLY under the following conditions, which this system meets: + // + // 1. Single-Writer Guarantee: The underlying Counter::State is thread-local. + // Only one thread will ever call inc() on a given instance. All writes + // and the non-atomic read below are therefore *sequenced*, not concurrent, + // preventing torn reads within this thread. + // + // 2. Atomic Visibility: The render thread is the only other thread that + // accesses this value, and it does so via an atomic load. A concurrent + // non-atomic read (writer) and atomic read (renderer) is not a data race. + // + // This contrasts with Gauges, whose state can be shared by multiple threads + // and thus requires a fully atomic read-modify-write cycle (CAS loop). auto new_value = p->value + x; // Validate monotonic property (counter never decreases)