From 8b579751103e0e182022dcabf38507e84081b995 Mon Sep 17 00:00:00 2001 From: Toby Lawrence Date: Mon, 16 Nov 2020 18:45:15 -0500 Subject: [PATCH] fix concurrent writer/uninitialized memory bug with AtomicBucket --- metrics-util/src/bucket.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/metrics-util/src/bucket.rs b/metrics-util/src/bucket.rs index 4ffc0fa..e3fc6ae 100644 --- a/metrics-util/src/bucket.rs +++ b/metrics-util/src/bucket.rs @@ -5,14 +5,19 @@ use std::{ sync::atomic::{AtomicUsize, Ordering}, }; -const BLOCK_SIZE: usize = 512; +#[cfg(target_pointer_width = "16")] +const BLOCK_SIZE: usize = 16; +#[cfg(target_pointer_width = "32")] +const BLOCK_SIZE: usize = 32; +#[cfg(target_pointer_width = "64")] +const BLOCK_SIZE: usize = 64; /// Discrete chunk of values with atomic read/write access. struct Block { // Write index. write: AtomicUsize, - // Read index. + // Read bitmap. read: AtomicUsize, // The individual slots. @@ -35,7 +40,7 @@ impl Block { /// Gets the current length of this block. pub fn len(&self) -> usize { - self.read.load(Ordering::Acquire) + self.read.load(Ordering::Acquire).trailing_ones() as usize } /// Gets a slice of the data written to this block. @@ -71,7 +76,7 @@ impl Block { } // Scoot our read index forward. - self.read.fetch_add(1, Ordering::AcqRel); + self.read.fetch_or(1 << index, Ordering::AcqRel); Ok(()) } @@ -324,6 +329,7 @@ mod tests { let result = block.push(42); assert!(result.is_ok()); + assert_eq!(block.len(), 1); let data = block.data(); assert_eq!(data.len(), 1);