1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
use crate::{HazardPtr, HazardRecord, HazardRegistry, HazardValue}; use std::sync::atomic::Ordering; pub struct HazardStack<T: Send + Clone> { hp: HazardPtr<Vec<T>>, } impl<T: Send + Clone> Default for HazardStack<T> { fn default() -> Self { let registry = HazardRegistry::default(); let hp = HazardPtr::new(HazardValue::boxed(Vec::new()), ®istry); HazardStack { hp } } } impl<T: Send + Clone> HazardStack<T> { pub fn push(&self, item: T) { let mut record = HazardRecord::default(); loop { let scope = self.hp.protect(&mut record); let reference = scope.as_ref().unwrap(); let mut new = (*reference).clone(); new.push(item.clone()); if scope .compare_exchange_weak( HazardValue::boxed(new), Ordering::Relaxed, Ordering::Relaxed, ) .is_ok() { break; } } } pub fn pop(&self) -> Option<T> { let mut record = HazardRecord::default(); loop { let scope = self.hp.protect(&mut record); let reference = scope.as_ref().unwrap(); let mut new = (*reference).clone(); let ret = new.pop(); if scope .compare_exchange_weak( HazardValue::boxed(new), Ordering::Relaxed, Ordering::Relaxed, ) .is_ok() { return ret; } } } pub fn take_inner(&self) -> Vec<T> { let value = self .hp .swap(HazardValue::boxed(Vec::new()), Ordering::Relaxed); value.take_safe().unwrap() } } #[test] pub fn test_hazard_vector() { use std::sync::Arc; use std::thread; let thread_count = 128; let loop_count = 53; let vec1 = Arc::new(HazardStack::<usize>::default()); let vec2 = Arc::new(HazardStack::<usize>::default()); let handles: Vec<_> = (0..thread_count) .into_iter() .map(|idx| { let cpy1 = vec1.clone(); let cpy2 = vec2.clone(); thread::spawn(move || { thread::park(); let start = idx * loop_count; for idx in start..start + loop_count { cpy1.push(idx); } for _ in 0..loop_count { cpy2.push(cpy1.pop().unwrap()); } }) }) .collect(); for child in handles.iter() { child.thread().unpark(); } for child in handles.into_iter() { child.join().unwrap(); } let vec1 = vec1.take_inner(); assert!(vec1.len() == 0, "expected vec1 to be empty"); let mut vec2 = vec2.take_inner(); vec2.sort(); for i in 0..vec2.len() { assert!(vec2[i] == i, "unexpected vec2 value"); } }