Skip to content

Commit 056a195

Browse files
author
Matthew Shapiro
committed
Finish
1 parent 8c3d9c1 commit 056a195

File tree

1 file changed

+25
-16
lines changed
  • opentelemetry-sdk/src/metrics/internal

1 file changed

+25
-16
lines changed

opentelemetry-sdk/src/metrics/internal/mod.rs

+25-16
Original file line numberDiff line numberDiff line change
@@ -140,19 +140,19 @@ impl AtomicallyUpdate<i64> for i64 {
140140
}
141141
}
142142

143-
pub(crate) struct F64AtomicTracker {
143+
pub(crate) struct F64AtomicValue {
144144
inner: Mutex<f64>, // Floating points don't have true atomics, so we need to use mutex for them
145145
}
146146

147-
impl F64AtomicTracker {
147+
impl F64AtomicValue {
148148
pub(crate) fn new() -> Self {
149-
F64AtomicTracker {
149+
F64AtomicValue {
150150
inner: Mutex::new(0.0),
151151
}
152152
}
153153
}
154154

155-
impl AtomicValue<f64> for F64AtomicTracker {
155+
impl AtomicValue<f64> for F64AtomicValue {
156156
fn add(&self, value: f64) {
157157
let mut guard = self.inner.lock().expect("F64 mutex was poisoned");
158158
*guard += value;
@@ -171,10 +171,10 @@ impl AtomicValue<f64> for F64AtomicTracker {
171171
}
172172

173173
impl AtomicallyUpdate<f64> for f64 {
174-
type AtomicValue = F64AtomicTracker;
174+
type AtomicValue = F64AtomicValue;
175175

176176
fn new_atomic_tracker() -> AtomicTracker<f64, Self::AtomicValue> {
177-
AtomicTracker::new(F64AtomicTracker::new())
177+
AtomicTracker::new(F64AtomicValue::new())
178178
}
179179
}
180180

@@ -188,6 +188,15 @@ impl<N, T: AtomicValue<N>> AtomicTracker<N, T> {
188188
}
189189

190190
pub(crate) fn add(&self, value: N) {
191+
// Technically we lose atomicity from using 2 atomics. However, the `add()` is specifically
192+
// designed mutate the value *then* set `has_value`, while the `get_value()` is designed
193+
// to read `has_value` *then* read the value. This means that in a worst case race
194+
// condition, the value added may get picked up from a previous `get_value()` call, but
195+
// the `has_value` being true will be picked up in the next `get_value()` call. This really
196+
// should only mean that the first export gets the added value, and the 2nd export will
197+
// get a 0 value.
198+
//
199+
// This doesn't seem like a big deal, and we avoid the cost of locking.
191200
self.value.add(value);
192201
self.has_value.store(true, Ordering::Release);
193202
}
@@ -226,11 +235,11 @@ mod tests {
226235
let atomic = u64::new_atomic_tracker();
227236
atomic.add(15);
228237

229-
let value = atomic.get_value(true).unwrap();
230-
let value2 = atomic.get_value(false).unwrap();
238+
let value = atomic.get_value(true);
239+
let value2 = atomic.get_value(false);
231240

232-
assert_eq!(value, 15, "Incorrect first value");
233-
assert_eq!(value2, 0, "Incorrect second value");
241+
assert_eq!(value, Some(15), "Incorrect first value");
242+
assert_eq!(value2, None, "Incorrect second value");
234243
}
235244

236245
#[test]
@@ -248,11 +257,11 @@ mod tests {
248257
let atomic = i64::new_atomic_tracker();
249258
atomic.add(15);
250259

251-
let value = atomic.get_value(true).unwrap();
252-
let value2 = atomic.get_value(false).unwrap();
260+
let value = atomic.get_value(true);
261+
let value2 = atomic.get_value(false);
253262

254-
assert_eq!(value, 15, "Incorrect first value");
255-
assert_eq!(value2, 0, "Incorrect second value");
263+
assert_eq!(value, Some(15), "Incorrect first value");
264+
assert_eq!(value2, None, "Incorrect second value");
256265
}
257266

258267
#[test]
@@ -272,9 +281,9 @@ mod tests {
272281
atomic.add(15.5);
273282

274283
let value = atomic.get_value(true).unwrap();
275-
let value2 = atomic.get_value(false).unwrap();
284+
let value2 = atomic.get_value(false);
276285

277286
assert!(f64::abs(15.5 - value) < 0.0001, "Incorrect first value");
278-
assert!(f64::abs(0.0 - value2) < 0.0001, "Incorrect second value");
287+
assert_eq!(value2, None, "Expected no value from second get_value call");
279288
}
280289
}

0 commit comments

Comments
 (0)