cs431_homework/hazard_pointer/
mod.rs

1//! Hazard pointers.
2//!
3//! # Example
4//!
5//! ```
6//! use std::ptr;
7//! use std::sync::atomic::{AtomicPtr, Ordering};
8//! use cs431_homework::hazard_pointer::{collect, retire, Shield};
9//!
10//! let shield = Shield::default();
11//! let atomic = AtomicPtr::new(Box::leak(Box::new(1usize)));
12//! let protected = shield.protect(&atomic);
13//! assert_eq!(unsafe { *protected }, 1);
14//!
15//! // unlink the block and retire
16//! atomic.store(ptr::null_mut(), Ordering::Relaxed);
17//! unsafe { retire(protected); }
18//!
19//! // manually trigger reclamation (not necessary)
20//! collect();
21//! ```
22
23use core::cell::RefCell;
24#[cfg(not(feature = "check-loom"))]
25use std::thread_local;
26
27#[cfg(feature = "check-loom")]
28use loom::thread_local;
29
30mod hazard;
31mod retire;
32
33pub use hazard::{HazardBag, Shield};
34pub use retire::RetiredSet;
35
36#[cfg(not(feature = "check-loom"))]
37/// Default global bag of all hazard pointers.
38pub static HAZARDS: HazardBag = HazardBag::new();
39
40#[cfg(feature = "check-loom")]
41// FIXME: loom does not currently provide the equivalent of Lazy:
42// https://github.com/tokio-rs/loom/issues/263
43loom::lazy_static! {
44    /// Default global bag of all hazard pointers.
45    pub static ref HAZARDS: HazardBag = HazardBag::new();
46}
47
48thread_local! {
49    /// Default thread-local retired pointer list.
50    static RETIRED: RefCell<RetiredSet<'static>> = RefCell::new(RetiredSet::default());
51}
52
53/// Retires a pointer.
54///
55/// # Safety
56///
57/// * `pointer` must be removed from shared memory before calling this function, and must be valid.
58/// * The same `pointer` should only be retired once.
59pub unsafe fn retire<T>(pointer: *mut T) {
60    RETIRED.with(|r| unsafe { r.borrow_mut().retire(pointer) });
61}
62
63/// Frees the pointers that are `retire`d by the current thread and not `protect`ed by any other
64/// threads.
65pub fn collect() {
66    RETIRED.with(|r| r.borrow_mut().collect());
67}