Struct nolock::hazard_ptr::Domain
source · [−]pub struct Domain { /* private fields */ }
Expand description
A Hazard-Pointer-Domain that can be used either globally as a shared Domain or as a per Object Domain to seperate the Domains of different Instances of Objects.
What is a Hazard-Pointer-Domain
A Hazard-Pointer-Domain is a collection of Hazard-Pointers and allows you to seperate different Parts of a System, where you know that they dont need access to the Hazard-Pointers of other Parts. This could lead to performance improvements as all the Parts only check the Hazard-Pointers that are actually relevant for them.
Where to use a different Hazard-Pointer-Domain
Like previously mentioned different Domains are useful to seperate an entire System into smaller Parts, however there are also other cases where having a custom Domain can be useful.
Seperating Datastructure Instances
Having seperate Domains for individual Datastructures can help with Performance, because for example if you have two Lists and they were to share a single Domain, List 1 has to check the Hazard-Pointers for List 2 everytime it needs to work with Hazard-Pointers although they are not relevant in that Case.
Implementations
sourceimpl Domain
impl Domain
sourcepub fn new(reclaim_threshold: usize) -> Self
pub fn new(reclaim_threshold: usize) -> Self
Creates a new Hazard-Pointer-Domain
Params
reclaim_threshold
: The Threshold for waiting Items before attempting
to reclaim Memory
sourcepub fn protect<T>(
&self,
atom_ptr: &AtomicPtr<T>,
load_order: Ordering
) -> Guard<T>
pub fn protect<T>(
&self,
atom_ptr: &AtomicPtr<T>,
load_order: Ordering
) -> Guard<T>
Reads the Data from the given AtomicPtr and protects it using a Hazard- Ptr. Returns you a Guard through which you can interact with the Data loaded from the AtomicPtr and as long as the Guard lives, the Data is safe to access and use
Example
let domain = hazard_ptr::Domain::new(10);
// Create an AtomicPtr with some Value
let ptr = Box::into_raw(Box::new(13));
let atom_ptr = atomic::AtomicPtr::new(ptr);
// Get protected Access to the Value pointed to
let guarded = domain.protect(&atom_ptr, atomic::Ordering::SeqCst);
// Access the inner Value
assert_eq!(13, *guarded);
unsafe {
// Retire/"Free" the Data
domain.retire(ptr, |p| { unsafe { Box::from_raw(p) }; });
}
// As long as we still have the Guard, the Data will not actually be
// reclaimed and can still be used safely
assert_eq!(13, *guarded);
sourcepub fn empty_guard<T>(&self) -> Guard<T>
pub fn empty_guard<T>(&self) -> Guard<T>
Creates a new empty Guard, that can then be used to protect any sort of Data behind an AtomicPtr.
sourcepub unsafe fn retire<T, F>(&self, ptr: *mut T, retire_fn: F)where
F: Fn(*mut T) + 'static,
pub unsafe fn retire<T, F>(&self, ptr: *mut T, retire_fn: F)where
F: Fn(*mut T) + 'static,
Marks the given Ptr as retired and once no more Hazard-Ptrs protect
the same Ptr, the given retire_fn
function will be called to
properly clean up the Data.
Note
There is no garantue as to when the given Ptr will actually be retired using the given function, because the Hazard-Pointer that protects the Data may be stored somewhere or the Thread that was responsible for it crashed/wont respond/is not running again and therefore can not mark it as unused anymore.
Safety
The given Pointer must not be reachable anymore, meaning that it can not be loaded anymore or any new Guards pointing to it can be created. However it is okay to have outstanding Guards pointing to it that may still be used and those are still valid.
This garantue is already held up by most algorithms as they first swap out the Pointer from any shared references and then perform a call to retire, which is valid in this case as the pointer can not be loaded anymore from the shared reference.
sourcepub fn reclaim(&self)
pub fn reclaim(&self)
Forces a reclaimation cycle, however this does not garantue that any Nodes/Ptrs will actually be reclaimed, as they might all still be protected/in use
Use Cases
This might be useful in a very performance sensitive application, where you want to avoid running the Reclaimation while in a Hot-Path. In these Cases, you can set the reclaimation threshold to a very large Value when creating the Domain, as to avoid triggering it by accident, and then call this function manually outside of the Hot-Path.
Trait Implementations
Auto Trait Implementations
impl !RefUnwindSafe for Domain
impl Send for Domain
impl Sync for Domain
impl Unpin for Domain
impl !UnwindSafe for Domain
Blanket Implementations
sourceimpl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more