Use std::bit_cast, document that gauge mutex is an implementation detail
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
//
|
//
|
||||||
// PRECISION STRATEGY:
|
// PRECISION STRATEGY:
|
||||||
// - Use atomic<uint64_t> for lock-free storage
|
// - Use atomic<uint64_t> for lock-free storage
|
||||||
// - Store doubles by reinterpreting bits as uint64_t (preserves full IEEE 754
|
// - Store doubles using std::bit_cast to uint64_t (preserves full IEEE 754
|
||||||
// precision)
|
// precision)
|
||||||
// - Single writer assumption allows simple load/store without CAS loops
|
// - Single writer assumption allows simple load/store without CAS loops
|
||||||
//
|
//
|
||||||
@@ -19,9 +19,9 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <bit>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@@ -74,15 +74,7 @@ using AtomicWord = std::atomic<uint64_t>;
|
|||||||
// DESIGN: Store doubles in atomic<uint64_t> for lock-free operations
|
// DESIGN: Store doubles in atomic<uint64_t> for lock-free operations
|
||||||
// - Preserves full IEEE 754 double precision (no truncation)
|
// - Preserves full IEEE 754 double precision (no truncation)
|
||||||
// - Allows atomic load/store without locks
|
// - Allows atomic load/store without locks
|
||||||
// - Safe bit-wise conversion between double and uint64_t
|
// - Use std::bit_cast for safe conversion between double and uint64_t
|
||||||
template <class U, class V> U reinterpret(V v) {
|
|
||||||
static_assert(sizeof(U) == sizeof(V));
|
|
||||||
static_assert(std::is_arithmetic_v<U>);
|
|
||||||
static_assert(std::is_arithmetic_v<V>);
|
|
||||||
U u;
|
|
||||||
memcpy(&u, &v, sizeof(u));
|
|
||||||
return u;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Family::State structures own the second-level maps (labels -> instances)
|
// Family::State structures own the second-level maps (labels -> instances)
|
||||||
template <> struct Family<Counter>::State {
|
template <> struct Family<Counter>::State {
|
||||||
@@ -235,11 +227,13 @@ void Counter::inc(double x) {
|
|||||||
// DESIGN: Single writer per thread allows simple load-modify-store
|
// DESIGN: Single writer per thread allows simple load-modify-store
|
||||||
// No CAS loop needed since only one thread writes to this counter
|
// No CAS loop needed since only one thread writes to this counter
|
||||||
auto current_value =
|
auto current_value =
|
||||||
reinterpret<double>(p->value.load(std::memory_order_relaxed));
|
std::bit_cast<double>(p->value.load(std::memory_order_relaxed));
|
||||||
p->value.store(reinterpret<uint64_t>(current_value + x),
|
p->value.store(std::bit_cast<uint64_t>(current_value + x),
|
||||||
std::memory_order_relaxed);
|
std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
void Gauge::inc(double x) {
|
void Gauge::inc(double x) {
|
||||||
|
// IMPLEMENTATION DETAIL: Gauges currently support multiple writers via mutex,
|
||||||
|
// though the public API documents single-writer semantics for consistency
|
||||||
std::unique_lock<std::mutex> _{p->mutex};
|
std::unique_lock<std::mutex> _{p->mutex};
|
||||||
p->value += x;
|
p->value += x;
|
||||||
}
|
}
|
||||||
@@ -263,8 +257,8 @@ void Histogram::observe(double x) {
|
|||||||
// DESIGN: Single writer per thread allows simple load-modify-store for sum
|
// DESIGN: Single writer per thread allows simple load-modify-store for sum
|
||||||
// No CAS loop needed since only one thread writes to this histogram
|
// No CAS loop needed since only one thread writes to this histogram
|
||||||
auto current_sum =
|
auto current_sum =
|
||||||
reinterpret<double>(p->sum.load(std::memory_order_relaxed));
|
std::bit_cast<double>(p->sum.load(std::memory_order_relaxed));
|
||||||
p->sum.store(reinterpret<uint64_t>(current_sum + x),
|
p->sum.store(std::bit_cast<uint64_t>(current_sum + x),
|
||||||
std::memory_order_relaxed);
|
std::memory_order_relaxed);
|
||||||
|
|
||||||
p->observations.fetch_add(1, std::memory_order_relaxed);
|
p->observations.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
|||||||
Reference in New Issue
Block a user