Struct sdd::Guard

source ·
pub struct Guard { /* private fields */ }
Expand description

Guard allows the user to read AtomicShared and keeps the underlying instance pinned to the thread.

Guard internally prevents the global epoch value from passing through the value announced by the current thread, thus keeping reachable instances in the thread from being garbage collected.

Implementations§

source§

impl Guard

source

pub fn new() -> Self

Creates a new Guard.

§Panics

The maximum number of Guard instances in a thread is limited to u32::MAX; a thread panics when the number of Guard instances in the thread exceeds the limit.

§Examples
use sdd::Guard;

let guard = Guard::new();
source

pub fn epoch(&self) -> Epoch

Returns the epoch in which the current thread lives.

This method can be used to check whether a retired memory region is potentially reachable or not. A chunk of memory retired in a witnessed Epoch can be deallocated after the thread has observed three new epochs. For instance, if the witnessed epoch value is 1 in the current thread where the global epoch value is 2, and an instance of a Collectible type is retired in the same thread, the instance can be dropped when the thread witnesses 0 which is three epochs away from 1.

In other words, there can be potential readers of the memory chunk until the current thread witnesses the previous epoch. In the above example, the global epoch can be in 2 while the current thread has only witnessed 1, and therefore there can a reader of the memory chunk in another thread in epoch 2. The reader can survive until the global epoch reaches 0 again, because the thread being in 2 prevents the global epoch from reaching 0.

§Examples
use sdd::{Guard, Owned};
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering::Relaxed;

static DROPPED: AtomicBool = AtomicBool::new(false);

struct D(&'static AtomicBool);

impl Drop for D {
    fn drop(&mut self) {
        self.0.store(true, Relaxed);
    }
}

let owned = Owned::new(D(&DROPPED));

let epoch_before = Guard::new().epoch();

drop(owned);
assert!(!DROPPED.load(Relaxed));

while Guard::new().epoch() == epoch_before {
    assert!(!DROPPED.load(Relaxed));
}

while Guard::new().epoch() == epoch_before.next() {
    assert!(!DROPPED.load(Relaxed));
}

while Guard::new().epoch() == epoch_before.next().next() {
    assert!(!DROPPED.load(Relaxed));
}

assert!(DROPPED.load(Relaxed));
assert_eq!(Guard::new().epoch(), epoch_before.prev());
source

pub fn accelerate(&self)

Forces the Guard to try to start a new epoch when it is dropped.

§Examples
use sdd::Guard;

let guard = Guard::new();

let epoch = guard.epoch();
guard.accelerate();

drop(guard);

assert_ne!(epoch, Guard::new().epoch());
source

pub fn defer(&self, collectible: Box<dyn Collectible>)

Defers dropping and memory reclamation of the supplied Box of a type implementing Collectible.

§Examples
use sdd::{Guard, Collectible};
use std::ptr::NonNull;

struct C(usize, Option<NonNull<dyn Collectible>>);

impl Collectible for C {
    fn next_ptr_mut(&mut self) -> &mut Option<NonNull<dyn Collectible>> {
        &mut self.1
    }
}

let boxed: Box<C> = Box::new(C(7, None));

let static_ref: &'static C = unsafe { std::mem::transmute(&*boxed) };

let guard = Guard::new();
guard.defer(boxed);

assert_eq!(static_ref.0, 7);
source

pub fn defer_execute<F: 'static + FnOnce()>(&self, f: F)

Executes the supplied closure at a later point of time.

It is guaranteed that the closure will be executed after every Guard at the moment when the method was invoked is dropped, however it is totally non-deterministic when exactly the closure will be executed.

§Examples
use sdd::Guard;

let guard = Guard::new();
guard.defer_execute(|| println!("deferred"));

Trait Implementations§

source§

impl Default for Guard

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl Drop for Guard

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl UnwindSafe for Guard

Auto Trait Implementations§

§

impl Freeze for Guard

§

impl !RefUnwindSafe for Guard

§

impl !Send for Guard

§

impl !Sync for Guard

§

impl Unpin for Guard

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.