diff --git a/src/encoding/text.rs b/src/encoding/text.rs index 26bac582..b1b0320d 100644 --- a/src/encoding/text.rs +++ b/src/encoding/text.rs @@ -103,6 +103,13 @@ impl Encode for f64 { } } +impl Encode for f32 { + fn encode(&self, writer: &mut dyn Write) -> Result<(), std::io::Error> { + writer.write_all(dtoa::Buffer::new().format(*self).as_bytes())?; + Ok(()) + } +} + impl Encode for u64 { fn encode(&self, writer: &mut dyn Write) -> Result<(), std::io::Error> { writer.write_all(itoa::Buffer::new().format(*self).as_bytes())?; diff --git a/src/metrics/counter.rs b/src/metrics/counter.rs index c8ad9461..b2140a1a 100644 --- a/src/metrics/counter.rs +++ b/src/metrics/counter.rs @@ -4,7 +4,7 @@ use super::{MetricType, TypedMetric}; use std::marker::PhantomData; -#[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] +#[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch = "xtensa")))] use std::sync::atomic::AtomicU64; use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::Arc; @@ -38,13 +38,13 @@ use std::sync::Arc; /// counter.inc(); /// let _value: f64 = counter.get(); /// ``` -#[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] +#[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch = "xtensa")))] pub struct Counter { value: Arc, phantom: PhantomData, } -#[cfg(any(target_arch = "mips", target_arch = "powerpc"))] +#[cfg(any(target_arch = "mips", target_arch = "powerpc", target_arch = "xtensa"))] pub struct Counter { value: Arc, phantom: PhantomData, @@ -105,7 +105,7 @@ pub trait Atomic { fn get(&self) -> N; } -#[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] +#[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch = "xtensa")))] impl Atomic for AtomicU64 { fn inc(&self) -> u64 { self.inc_by(1) @@ -134,31 +134,44 @@ impl Atomic for AtomicU32 { } } -#[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] -impl Atomic for AtomicU64 { - fn inc(&self) -> f64 { - self.inc_by(1.0) - } +macro_rules! atomic_float { + ($F:ty, $A:ty) => { + impl Atomic<$F> for $A { + fn inc(&self) -> $F { + self.inc_by(1.0) + } + + fn inc_by(&self, v: $F) -> $F { + let mut old_atom = self.load(Ordering::Relaxed); + let mut old_flt; + loop { + old_flt = <$F>::from_bits(old_atom); + let new = <$F>::to_bits(old_flt + v); + match self.compare_exchange_weak( + old_atom, + new, + Ordering::Relaxed, + Ordering::Relaxed, + ) { + Ok(_) => break, + Err(x) => old_atom = x, + } + } + + old_flt + } - fn inc_by(&self, v: f64) -> f64 { - let mut old_u64 = self.load(Ordering::Relaxed); - let mut old_f64; - loop { - old_f64 = f64::from_bits(old_u64); - let new = f64::to_bits(old_f64 + v); - match self.compare_exchange_weak(old_u64, new, Ordering::Relaxed, Ordering::Relaxed) { - Ok(_) => break, - Err(x) => old_u64 = x, + fn get(&self) -> $F { + <$F>::from_bits(self.load(Ordering::Relaxed)) } } + }; +} - old_f64 - } +#[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch = "xtensa")))] +atomic_float!(f64, AtomicU64); - fn get(&self) -> f64 { - f64::from_bits(self.load(Ordering::Relaxed)) - } -} +atomic_float!(f32, AtomicU32); impl TypedMetric for Counter { const TYPE: MetricType = MetricType::Counter; @@ -176,7 +189,7 @@ mod tests { assert_eq!(1, counter.get()); } - #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] + #[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch = "xtensa")))] #[test] fn f64_stored_in_atomic_u64() { fn prop(fs: Vec) { diff --git a/src/metrics/exemplar.rs b/src/metrics/exemplar.rs index 66a043bb..d7a1c533 100644 --- a/src/metrics/exemplar.rs +++ b/src/metrics/exemplar.rs @@ -6,9 +6,9 @@ use super::counter::{self, Counter}; use super::histogram::Histogram; use owning_ref::OwningRef; use std::collections::HashMap; -#[cfg(any(target_arch = "mips", target_arch = "powerpc"))] +#[cfg(any(target_arch = "mips", target_arch = "powerpc", target_arch="xtensa"))] use std::sync::atomic::AtomicU32; -#[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] +#[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch="xtensa")))] use std::sync::atomic::AtomicU64; use std::sync::{Arc, RwLock, RwLockReadGuard}; @@ -29,12 +29,12 @@ pub struct Exemplar { /// counter_with_exemplar.inc_by(1, Some(vec![("user_id".to_string(), "42".to_string())])); /// let _value: (u64, _) = counter_with_exemplar.get(); /// ``` -#[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] +#[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch="xtensa")))] pub struct CounterWithExemplar { pub(crate) inner: Arc>>, } -#[cfg(any(target_arch = "mips", target_arch = "powerpc"))] +#[cfg(any(target_arch = "mips", target_arch = "powerpc", target_arch="xtensa"))] pub struct CounterWithExemplar { pub(crate) inner: Arc>>, } diff --git a/src/metrics/gauge.rs b/src/metrics/gauge.rs index 504d5bd9..28ae268a 100644 --- a/src/metrics/gauge.rs +++ b/src/metrics/gauge.rs @@ -4,7 +4,7 @@ use super::{MetricType, TypedMetric}; use std::marker::PhantomData; -#[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] +#[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch = "xtensa")))] use std::sync::atomic::AtomicU64; use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::Arc; @@ -38,13 +38,13 @@ use std::sync::Arc; /// gauge.set(42.0); /// let _value: f64 = gauge.get(); /// ``` -#[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] +#[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch = "xtensa")))] pub struct Gauge { value: Arc, phantom: PhantomData, } -#[cfg(any(target_arch = "mips", target_arch = "powerpc"))] +#[cfg(any(target_arch = "mips", target_arch = "powerpc", target_arch = "xtensa"))] pub struct Gauge { value: Arc, phantom: PhantomData, @@ -122,7 +122,7 @@ pub trait Atomic { fn get(&self) -> N; } -#[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] +#[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch = "xtensa")))] impl Atomic for AtomicU64 { fn inc(&self) -> u64 { self.inc_by(1) @@ -175,55 +175,73 @@ impl Atomic for AtomicU32 { } } -#[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] -impl Atomic for AtomicU64 { - fn inc(&self) -> f64 { - self.inc_by(1.0) - } - - fn inc_by(&self, v: f64) -> f64 { - let mut old_u64 = self.load(Ordering::Relaxed); - let mut old_f64; - loop { - old_f64 = f64::from_bits(old_u64); - let new = f64::to_bits(old_f64 + v); - match self.compare_exchange_weak(old_u64, new, Ordering::Relaxed, Ordering::Relaxed) { - Ok(_) => break, - Err(x) => old_u64 = x, +macro_rules! atomic_float { + ($F:ty, $A:ty) => { + impl Atomic<$F> for $A { + fn inc(&self) -> $F { + self.inc_by(1.0) } - } - - old_f64 - } - fn dec(&self) -> f64 { - self.dec_by(1.0) - } + fn inc_by(&self, v: $F) -> $F { + let mut old_atom = self.load(Ordering::Relaxed); + let mut old_flt; + loop { + old_flt = <$F>::from_bits(old_atom); + let new = <$F>::to_bits(old_flt + v); + match self.compare_exchange_weak( + old_atom, + new, + Ordering::Relaxed, + Ordering::Relaxed, + ) { + Ok(_) => break, + Err(x) => old_atom = x, + } + } + + old_flt + } - fn dec_by(&self, v: f64) -> f64 { - let mut old_u64 = self.load(Ordering::Relaxed); - let mut old_f64; - loop { - old_f64 = f64::from_bits(old_u64); - let new = f64::to_bits(old_f64 - v); - match self.compare_exchange_weak(old_u64, new, Ordering::Relaxed, Ordering::Relaxed) { - Ok(_) => break, - Err(x) => old_u64 = x, + fn dec(&self) -> $F { + self.dec_by(1.0) } - } - old_f64 - } + fn dec_by(&self, v: $F) -> $F { + let mut old_atom = self.load(Ordering::Relaxed); + let mut old_flt; + loop { + old_flt = <$F>::from_bits(old_atom); + let new = <$F>::to_bits(old_flt - v); + match self.compare_exchange_weak( + old_atom, + new, + Ordering::Relaxed, + Ordering::Relaxed, + ) { + Ok(_) => break, + Err(x) => old_atom = x, + } + } + + old_flt + } - fn set(&self, v: f64) -> f64 { - f64::from_bits(self.swap(f64::to_bits(v), Ordering::Relaxed)) - } + fn set(&self, v: $F) -> $F { + <$F>::from_bits(self.swap(<$F>::to_bits(v), Ordering::Relaxed)) + } - fn get(&self) -> f64 { - f64::from_bits(self.load(Ordering::Relaxed)) - } + fn get(&self) -> $F { + <$F>::from_bits(self.load(Ordering::Relaxed)) + } + } + }; } +#[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch = "xtensa")))] +atomic_float!(f64, AtomicU64); + +atomic_float!(f32, AtomicU32); + impl TypedMetric for Gauge { const TYPE: MetricType = MetricType::Gauge; }