Struct NonceStack

Source
pub struct NonceStack<T>
where T: Send,
{ /* private fields */ }

Implementations§

Source§

impl<T> NonceStack<T>
where T: Send,

Source

pub fn push(&self, val: T)

Source

pub fn pop(&self) -> Option<T>

Almost-correct example of using a nonce to implement pop().

This method contains a use-after-free on the line head.head=(*ret).next.

This would be safe in a garbage collected system, or in an embedded system without memory protection, since head.head will be discarded if the stack has been changed, and *ret can only be freed after it is popped from the stack. Since *ret may have been freed, it may have been returned to the operating system, leading to a segmentation fault when accessed here.

If you need a stack similar to NonceStack, consider using an epoch collector such as crossbeam_epoch, or by maintaining a pool of reusable objects. For instance, you could use a second stack to store the pool, and return objects to it after they are popped from this stack. If the pool stack is empty, then allocate a new object.

Once you are sure that no thread will access either stack, you can safely empty both stacks and free the objects they contain.

Stacks with nonces are also sometimes used to implement slot allocators. A slot allocator is initialized at startup with a finite number of tokens (such as file handles, or some other finite resource). When a thread needs a resource, it pops from the stack. If the stack is empty, then the thread goes async. Atomically checking that the stack is empty and registering oneself for future wakeup is left as an exercise to the reader, as it is exactly the sort of thing atomic_try_update excels at.

TODO: Implement a double-stack structure and/or slot such as the ones above, so we have correct examples of the NonceStack pattern.

Trait Implementations§

Source§

impl<T> Default for NonceStack<T>
where T: Send,

Source§

fn default() -> NonceStack<T>

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

impl<T> Drop for NonceStack<T>
where T: Send,

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl<T> !Freeze for NonceStack<T>

§

impl<T> RefUnwindSafe for NonceStack<T>
where T: RefUnwindSafe,

§

impl<T> Send for NonceStack<T>

§

impl<T> Sync for NonceStack<T>

§

impl<T> Unpin for NonceStack<T>

§

impl<T> UnwindSafe for NonceStack<T>
where T: RefUnwindSafe,

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>,

Source§

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>,

Source§

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.