From 80cfac24d50eaee07f5880328da6a92ebe707b4b Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Sat, 7 Sep 2019 17:17:36 +0200 Subject: [PATCH 1/6] Rewrite Bag without using ArrayVec --- crossbeam-epoch/src/internal.rs | 51 ++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/crossbeam-epoch/src/internal.rs b/crossbeam-epoch/src/internal.rs index 819e6bdc1..ec11f1a13 100644 --- a/crossbeam-epoch/src/internal.rs +++ b/crossbeam-epoch/src/internal.rs @@ -42,7 +42,6 @@ use core::ptr; use core::sync::atomic; use core::sync::atomic::Ordering; -use arrayvec::ArrayVec; use crossbeam_utils::CachePadded; use atomic::{Shared, Owned}; @@ -60,10 +59,11 @@ const MAX_OBJECTS: usize = 64; const MAX_OBJECTS: usize = 4; /// A bag of deferred functions. -#[derive(Default, Debug)] +// can't #[derive(Debug)] because Debug is not implemented for arrays 64 items long pub struct Bag { /// Stashed objects. - deferreds: ArrayVec<[Deferred; MAX_OBJECTS]>, + deferreds: [Deferred; MAX_OBJECTS], + len: usize } /// `Bag::try_push()` requires that it is safe for another thread to execute the given functions. @@ -77,7 +77,7 @@ impl Bag { /// Returns `true` if the bag is empty. pub fn is_empty(&self) -> bool { - self.deferreds.is_empty() + self.len == 0 } /// Attempts to insert a deferred function into the bag. @@ -89,7 +89,13 @@ impl Bag { /// /// It should be safe for another thread to execute the given function. pub unsafe fn try_push(&mut self, deferred: Deferred) -> Result<(), Deferred> { - self.deferreds.try_push(deferred).map_err(|e| e.element()) + if self.len < MAX_OBJECTS { + self.deferreds[self.len] = deferred; + self.len += 1; + Ok(()) + } else { + Err(deferred) + } } /// Seals the bag with the given epoch. @@ -98,17 +104,48 @@ impl Bag { } } +impl Default for Bag { + fn default() -> Self { + // [no_op; MAX_OBJECTS] blocked by https://github.com/rust-lang/rust/issues/49147 + #[cfg(not(feature = "sanitize"))] + return Bag { len: 0, deferreds: + [Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), + Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func)] + }; + #[cfg(feature = "sanitize")] + return Bag { len: 0, deferreds: [Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func)] }; + } +} + impl Drop for Bag { fn drop(&mut self) { // Call all deferred functions. - for deferred in self.deferreds.drain(..) { + for i in 0..self.len { + let no_op = Deferred::new(no_op_func); + let deferred = mem::replace(&mut self.deferreds[i], no_op); deferred.call(); } } } +fn no_op_func() {} + /// A pair of an epoch and a bag. -#[derive(Default, Debug)] +#[derive(Default)] struct SealedBag { epoch: Epoch, bag: Bag, From c596c156f63fc64c40223e71b24bc5ca032b548e Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Sat, 7 Sep 2019 17:21:02 +0200 Subject: [PATCH 2/6] Drop ArrayVec dependency from Cargo.toml, etc. --- crossbeam-epoch/Cargo.toml | 6 +----- crossbeam-epoch/src/lib.rs | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/crossbeam-epoch/Cargo.toml b/crossbeam-epoch/Cargo.toml index 16d447578..79e0f5ec9 100644 --- a/crossbeam-epoch/Cargo.toml +++ b/crossbeam-epoch/Cargo.toml @@ -17,7 +17,7 @@ categories = ["concurrency", "memory-management", "no-std"] [features] default = ["std"] -nightly = ["crossbeam-utils/nightly", "arrayvec/use_union"] +nightly = ["crossbeam-utils/nightly"] std = ["crossbeam-utils/std", "lazy_static"] alloc = ["crossbeam-utils/alloc"] sanitize = [] # Makes it more likely to trigger any potential data races. @@ -26,10 +26,6 @@ sanitize = [] # Makes it more likely to trigger any potential data races. cfg-if = "0.1.2" memoffset = "0.5" -[dependencies.arrayvec] -version = "0.4" -default-features = false - [dependencies.crossbeam-utils] version = "0.6" path = "../crossbeam-utils" diff --git a/crossbeam-epoch/src/lib.rs b/crossbeam-epoch/src/lib.rs index 8ff4bfd30..e3116dcf7 100644 --- a/crossbeam-epoch/src/lib.rs +++ b/crossbeam-epoch/src/lib.rs @@ -79,7 +79,6 @@ cfg_if! { )] cfg_if! { if #[cfg(any(feature = "alloc", feature = "std"))] { - extern crate arrayvec; extern crate crossbeam_utils; #[macro_use] extern crate memoffset; From 86c6bff5fe2708fec69fc2878612eae54b4a7620 Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Sat, 7 Sep 2019 18:24:07 +0200 Subject: [PATCH 3/6] Implement Debug for Bag manually --- crossbeam-epoch/src/internal.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/crossbeam-epoch/src/internal.rs b/crossbeam-epoch/src/internal.rs index ec11f1a13..462e8532e 100644 --- a/crossbeam-epoch/src/internal.rs +++ b/crossbeam-epoch/src/internal.rs @@ -59,7 +59,6 @@ const MAX_OBJECTS: usize = 64; const MAX_OBJECTS: usize = 4; /// A bag of deferred functions. -// can't #[derive(Debug)] because Debug is not implemented for arrays 64 items long pub struct Bag { /// Stashed objects. deferreds: [Deferred; MAX_OBJECTS], @@ -142,10 +141,25 @@ impl Drop for Bag { } } +// can't #[derive(Debug)] because Debug is not implemented for arrays 64 items long +impl core::fmt::Debug for Bag { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "Bag {{ deferreds: [")?; + if ! self.is_empty() { + write!(f, "{:?}", self.deferreds[0])?; + } + for i in 1..self.len { + write!(f, ", {:?}", self.deferreds[i])?; + } + write!(f, "] }}")?; + Ok(()) + } +} + fn no_op_func() {} /// A pair of an epoch and a bag. -#[derive(Default)] +#[derive(Default, Debug)] struct SealedBag { epoch: Epoch, bag: Bag, From 373f37fdca77d4fc546a3baa8940a5be942e2f28 Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Sat, 7 Sep 2019 19:05:07 +0200 Subject: [PATCH 4/6] More concise Debug implementation --- crossbeam-epoch/src/internal.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/crossbeam-epoch/src/internal.rs b/crossbeam-epoch/src/internal.rs index 462e8532e..da15457da 100644 --- a/crossbeam-epoch/src/internal.rs +++ b/crossbeam-epoch/src/internal.rs @@ -144,15 +144,7 @@ impl Drop for Bag { // can't #[derive(Debug)] because Debug is not implemented for arrays 64 items long impl core::fmt::Debug for Bag { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - write!(f, "Bag {{ deferreds: [")?; - if ! self.is_empty() { - write!(f, "{:?}", self.deferreds[0])?; - } - for i in 1..self.len { - write!(f, ", {:?}", self.deferreds[i])?; - } - write!(f, "] }}")?; - Ok(()) + f.debug_struct("Bag").field("deferreds", &&self.deferreds[..self.len]).finish() } } From 4ec94c8a97a30a7201c55bef4492acf2bd6c5ffc Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Thu, 12 Sep 2019 17:27:44 +0200 Subject: [PATCH 5/6] Mark ugly array initialization as TODO --- crossbeam-epoch/src/internal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crossbeam-epoch/src/internal.rs b/crossbeam-epoch/src/internal.rs index da15457da..ac383101f 100644 --- a/crossbeam-epoch/src/internal.rs +++ b/crossbeam-epoch/src/internal.rs @@ -105,7 +105,7 @@ impl Bag { impl Default for Bag { fn default() -> Self { - // [no_op; MAX_OBJECTS] blocked by https://github.com/rust-lang/rust/issues/49147 + // TODO: [no_op; MAX_OBJECTS] syntax blocked by https://github.com/rust-lang/rust/issues/49147 #[cfg(not(feature = "sanitize"))] return Bag { len: 0, deferreds: [Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), From 1349724913a17e37ecfb48795b561680d5aff692 Mon Sep 17 00:00:00 2001 From: Wojciech Nawrocki Date: Tue, 17 Sep 2019 14:31:15 +0000 Subject: [PATCH 6/6] Fix 1.28.0 build --- crossbeam-epoch/src/internal.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crossbeam-epoch/src/internal.rs b/crossbeam-epoch/src/internal.rs index ac383101f..d43e2b766 100644 --- a/crossbeam-epoch/src/internal.rs +++ b/crossbeam-epoch/src/internal.rs @@ -38,7 +38,7 @@ use core::cell::{Cell, UnsafeCell}; use core::mem::{self, ManuallyDrop}; use core::num::Wrapping; -use core::ptr; +use core::{ptr, fmt}; use core::sync::atomic; use core::sync::atomic::Ordering; @@ -142,8 +142,8 @@ impl Drop for Bag { } // can't #[derive(Debug)] because Debug is not implemented for arrays 64 items long -impl core::fmt::Debug for Bag { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { +impl fmt::Debug for Bag { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Bag").field("deferreds", &&self.deferreds[..self.len]).finish() } }