aboutsummaryrefslogtreecommitdiff
path: root/vendor/once_cell/tests/it/race_once_box.rs
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-01-08 00:21:28 +0300
committerValentin Popov <valentin@popov.link>2024-01-08 00:21:28 +0300
commit1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch)
tree7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/once_cell/tests/it/race_once_box.rs
parent5ecd8cf2cba827454317368b68571df0d13d7842 (diff)
downloadfparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz
fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/once_cell/tests/it/race_once_box.rs')
-rw-r--r--vendor/once_cell/tests/it/race_once_box.rs145
1 files changed, 145 insertions, 0 deletions
diff --git a/vendor/once_cell/tests/it/race_once_box.rs b/vendor/once_cell/tests/it/race_once_box.rs
new file mode 100644
index 0000000..0bf3852
--- /dev/null
+++ b/vendor/once_cell/tests/it/race_once_box.rs
@@ -0,0 +1,145 @@
+#[cfg(feature = "std")]
+use std::sync::Barrier;
+use std::sync::{
+ atomic::{AtomicUsize, Ordering::SeqCst},
+ Arc,
+};
+
+use once_cell::race::OnceBox;
+
+#[derive(Default)]
+struct Heap {
+ total: Arc<AtomicUsize>,
+}
+
+#[derive(Debug)]
+struct Pebble<T> {
+ val: T,
+ total: Arc<AtomicUsize>,
+}
+
+impl<T> Drop for Pebble<T> {
+ fn drop(&mut self) {
+ self.total.fetch_sub(1, SeqCst);
+ }
+}
+
+impl Heap {
+ fn total(&self) -> usize {
+ self.total.load(SeqCst)
+ }
+ fn new_pebble<T>(&self, val: T) -> Pebble<T> {
+ self.total.fetch_add(1, SeqCst);
+ Pebble { val, total: Arc::clone(&self.total) }
+ }
+}
+
+#[cfg(feature = "std")]
+#[test]
+fn once_box_smoke_test() {
+ use std::thread::scope;
+
+ let heap = Heap::default();
+ let global_cnt = AtomicUsize::new(0);
+ let cell = OnceBox::new();
+ let b = Barrier::new(128);
+ scope(|s| {
+ for _ in 0..128 {
+ s.spawn(|| {
+ let local_cnt = AtomicUsize::new(0);
+ cell.get_or_init(|| {
+ global_cnt.fetch_add(1, SeqCst);
+ local_cnt.fetch_add(1, SeqCst);
+ b.wait();
+ Box::new(heap.new_pebble(()))
+ });
+ assert_eq!(local_cnt.load(SeqCst), 1);
+
+ cell.get_or_init(|| {
+ global_cnt.fetch_add(1, SeqCst);
+ local_cnt.fetch_add(1, SeqCst);
+ Box::new(heap.new_pebble(()))
+ });
+ assert_eq!(local_cnt.load(SeqCst), 1);
+ });
+ }
+ });
+ assert!(cell.get().is_some());
+ assert!(global_cnt.load(SeqCst) > 10);
+
+ assert_eq!(heap.total(), 1);
+ drop(cell);
+ assert_eq!(heap.total(), 0);
+}
+
+#[test]
+fn once_box_set() {
+ let heap = Heap::default();
+ let cell = OnceBox::new();
+ assert!(cell.get().is_none());
+
+ assert!(cell.set(Box::new(heap.new_pebble("hello"))).is_ok());
+ assert_eq!(cell.get().unwrap().val, "hello");
+ assert_eq!(heap.total(), 1);
+
+ assert!(cell.set(Box::new(heap.new_pebble("world"))).is_err());
+ assert_eq!(cell.get().unwrap().val, "hello");
+ assert_eq!(heap.total(), 1);
+
+ drop(cell);
+ assert_eq!(heap.total(), 0);
+}
+
+#[cfg(feature = "std")]
+#[test]
+fn once_box_first_wins() {
+ use std::thread::scope;
+
+ let cell = OnceBox::new();
+ let val1 = 92;
+ let val2 = 62;
+
+ let b1 = Barrier::new(2);
+ let b2 = Barrier::new(2);
+ let b3 = Barrier::new(2);
+ scope(|s| {
+ s.spawn(|| {
+ let r1 = cell.get_or_init(|| {
+ b1.wait();
+ b2.wait();
+ Box::new(val1)
+ });
+ assert_eq!(*r1, val1);
+ b3.wait();
+ });
+ b1.wait();
+ s.spawn(|| {
+ let r2 = cell.get_or_init(|| {
+ b2.wait();
+ b3.wait();
+ Box::new(val2)
+ });
+ assert_eq!(*r2, val1);
+ });
+ });
+
+ assert_eq!(cell.get(), Some(&val1));
+}
+
+#[test]
+fn once_box_reentrant() {
+ let cell = OnceBox::new();
+ let res = cell.get_or_init(|| {
+ cell.get_or_init(|| Box::new("hello".to_string()));
+ Box::new("world".to_string())
+ });
+ assert_eq!(res, "hello");
+}
+
+#[test]
+fn once_box_default() {
+ struct Foo;
+
+ let cell: OnceBox<Foo> = Default::default();
+ assert!(cell.get().is_none());
+}