[][src]Trait pui::Identifier

pub unsafe trait Identifier: Eq {
    type Handle: Handle;
    pub fn handle(&self) -> Self::Handle;
pub fn owns(&self, handle: &Self::Handle) -> bool; }

An Identifier is a process unique identifier

you are guaranteed that two instances of this identifier will never compare equal You can also get a cheap handle to the identifier, which you can use to mark other types as logically owned by the identifier.

For example, this pattern is sound

use pui::Identifier;
use std::cell::UnsafeCell;

struct Owner<I> {
    ident: I,
}

struct Handle<H, T: ?Sized> {
    handle: H,
    value: UnsafeCell<T>,
}

impl<H, T> Handle<H, T> {
    pub fn new(handle: H, value: T) -> Self {
        Self { handle, value: UnsafeCell::new(value) }
    }
}

impl<I> Owner<I> {
    pub fn new(ident: I) -> Self {
        Self { ident }
    }
}

impl<I: Identifier> Owner<I> {
    pub fn read<'a, T: ?Sized>(&'a self, handle: &'a Handle<I::Handle, T>) -> &'a T {
        assert!(self.ident.owns(&handle.handle));
         
        // This is safe because `ident` owns the `handle`, which means that `self`
        // is the only `Owner` that could shared access the underlying value
        // This is because:
        //  * the `Owner` owns the `Identifier`
        //  * when we read/write, we bind the lifetime of `self` and `Handle`
        //      to the lifetime of the output reference
        //  * we have shared access to `*self`
         
        unsafe { &*handle.value.get() }
    }

    pub fn write<'a, T: ?Sized>(&'a mut self, handle: &'a Handle<I::Handle, T>) -> &'a mut T {
        assert!(self.ident.owns(&handle.handle));
         
        // This is safe because `ident` owns the `handle`, which means that `self`
        // is the only `Owner` that could exclusive access the underlying value
        // This is because:
        //  * the `Owner` owns the `Identifier`
        //  * when we read/write, we bind the lifetime of `self` and `Handle`
        //      to the lifetime of the output reference
        //  * we have exclusive access to `*self`
         
        unsafe { &mut *handle.value.get() }
    }
}

Safety

  • ident.owns(&handle) must return true for any handle returned from ident.handle() regardless of when the handle was created.
  • If two handles compare equal, then Identifier::owns must act the same for both of them
    • i.e. it must return false for both handles, or it must return true for both handles
  • Two instances of Identifier must never return true for the same handle if they can both exist on the same thread.
  • In particular, it is unsound to implement Identifier on references

Associated Types

type Handle: Handle[src]

A handle which can be used to mark other types

Loading content...

Required methods

pub fn handle(&self) -> Self::Handle[src]

Create a handle that this identifier owns

pub fn owns(&self, handle: &Self::Handle) -> bool[src]

Check the current identifier owns the given handle

Loading content...

Implementations on Foreign Types

impl<I: Identifier + ?Sized> Identifier for Box<I>[src]

type Handle = I::Handle

Loading content...

Implementors

impl<'id> Identifier for Scoped<'id>[src]

type Handle = ScopedHandle<'id>

impl<I: IdAlloc, P: PoolMut<I::Id>> Identifier for Runtime<I, P>[src]

type Handle = RuntimeHandle<I>

impl<T> Identifier for pui::typeid::Type<T>[src]

type Handle = TypeHandle<T>

impl<T> Identifier for pui::typeid_tl::Type<T>[src]

This is supported on crate feature std only.

type Handle = TypeHandle<T>

Loading content...