[][src]Trait reclaim::Reclaim

pub unsafe trait Reclaim where
    Self: Sized + 'static, 
{ type Local: Sized; type RecordHeader: Default + Sync + Sized; unsafe fn retire_local<T: 'static, N: Unsigned>(
        local: &Self::Local,
        unlinked: Unlinked<T, Self, N>
    );
unsafe fn retire_local_unchecked<T, N: Unsigned>(
        local: &Self::Local,
        unlinked: Unlinked<T, Self, N>
    ); unsafe fn retire_local_raw<T, N: Unsigned>(
        local: &Self::Local,
        ptr: MarkedPtr<T, N>
    ) { ... } }

A trait, which constitutes the foundation for the GlobalReclaim trait.

This trait is specifically intended to be fully compatible with #[no_std] environments. This is expressed by the requirement to explicitly pass references to thread local state or storage when calling functions that retire records.

If a reclamation scheme does not require or deliberately chooses to avoid using thread local storage for the sake of simplicity or portability (usually at the cost of performance), it is valid to implement Self::Local as () and pass all retired records directly through to some global state. Note, that this will generally require more and also more frequent synchronization. For cases in which Local is defined to be (), there exists a blanket implementation of `GlobalReclaim.

Associated Types

type Local: Sized

The type used for storing all relevant thread local state.

type RecordHeader: Default + Sync + Sized

Every record allocates this type alongside itself to store additional reclamation scheme specific data. When no such data is required, () is the recommended choice.

Loading content...

Required methods

unsafe fn retire_local<T: 'static, N: Unsigned>(
    local: &Self::Local,
    unlinked: Unlinked<T, Self, N>
)

Retires a record and caches it at least until it is safe to deallocate it.

How to determine that no other thread can possibly have any (protected) reference to a record depends on the respective reclamation scheme.

Safety

The caller has to guarantee that the record is fully unlinked from any data structure it was previously inserted in: There must be no way for another thread to acquire a new reference to the given unlinked record.

While an Unlinked value can only safely be obtained by atomic operations that do in fact remove a value from its place in memory (i.e. swap or compare-and-swap), this is only the necessary condition for safe reclamation, but not always sufficient. When a unique address to heap allocated memory is inserted in more than one element of a shared data structure, it is still possible for other threads to access this address even if its unlinked from one spot.

This invariant also mandates, that correct synchronization of atomic operations around calls to functions that retire records is ensured. Consider the following (incorrect) example:

This example is not tested

let g = Atomic::from(Owned::new(1));

// thread 1
let expected = g.load_unprotected(Relaxed); // reads &1
let unlinked = g
    .compare_exchange(expected, Owned::null(), Relaxed, Relaxed)
    .unwrap();

unsafe { unlinked.retire() };

// thread 2
if let Some(shared) = g.load(Relaxed, &mut guard) {
    assert_eq!(*shared, &1); // !!! may read freed memory
}

In this example, the invariant can not be guaranteed to be maintained, due to the incorrect (relaxed) memory orderings. Thread 1 can potentially unlink the shared value, retire and reclaim it, without the compare_exchange operation ever becoming visible to thread 2. The thread could then proceed to load and read the previous value instead of the inserted null, accessing freed memory.

unsafe fn retire_local_unchecked<T, N: Unsigned>(
    local: &Self::Local,
    unlinked: Unlinked<T, Self, N>
)

Retires a record and caches it at least until it is safe to deallocate it.

How to determine that no other thread can possibly have any (protected) reference to a record depends on the respective reclamation scheme.

Safety

The same restrictions as with the retire_local function apply here as well.

In addition to these invariants, this method additionally requires the caller to ensure any Drop implementation for T or any contained type does not access any non-static references. The reclaim interface makes no guarantees about the precise time a retired record is actually reclaimed. Hence, it is not possible to ensure any references stored within the record have not become invalid at that point.

Loading content...

Provided methods

unsafe fn retire_local_raw<T, N: Unsigned>(
    local: &Self::Local,
    ptr: MarkedPtr<T, N>
)

Retires a raw marked pointer to a record.

Safety

The same restrictions as with retire_local_unchecked apply. Since this function accepts a raw pointer, no type level checks on the validity are possible and are hence the responsibility of the caller.

Panics

In debug mode, this function panics if ptr is null.

Loading content...

Implementors

impl Reclaim for Leaking[src]

type Local = ()

type RecordHeader = ()

unsafe fn retire_local<T: 'static, N: Unsigned>(_: &(), _: Unlinked<T, N>)[src]

Leaks the given value.

Safety

Contrary to the specifications of the trait's method, this particular implementation is always safe to call.

unsafe fn retire_local_unchecked<T, N: Unsigned>(_: &(), _: Unlinked<T, N>)[src]

Leaks the given value.

Safety

Contrary to the specifications of the trait's method, this particular implementation is always safe to call.

Loading content...