1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#![cfg_attr(not(feature = "std"), no_std)]
#![allow(clippy::declare_interior_mutable_const)]
#![forbid(missing_docs, clippy::missing_safety_doc)]

//! `pui-core` provides process unique identifiers. These identifiers, as the name
//! suggests are unique within the process they reside in. `pui-core` also provides
//! thread-local unique identifiers that are unique within the thread they reside in.
//!
/// These identifiers can be used to enable safe (mostly) compile-time checked
/// shared mutability.
///
/// ```rust
/// 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() }
///     }
/// }
/// ```
///

#[cfg(all(not(feature = "std"), feature = "alloc",))]
extern crate alloc as std;

#[doc(hidden)]
pub mod export;
pub mod pool;
pub mod scalar;

pub mod dynamic;
pub mod scoped;
pub mod ty;

pub(crate) use seal::Seal;
#[forbid(missing_docs)]
mod seal {
    pub trait Seal {}
}

/// A const initializer
pub trait Init {
    /// The initial value of `Self`
    const INIT: Self;
}

/// A type that an [`Identifier`] produces and is owned by an `Identifier`
///
/// If two tokens compare equal, then they should behave identically under
/// `Identifier::owns_token` operation.
///
/// # Safety
///
/// * it should be not possible to change the behavior of `PartialEq::eq`
///   or `Identifier::owns_token` via a shared reference to a `Token`
/// * clones/copies of a token should be equal to each other
pub unsafe trait Token: Clone + Eq {}
/// A [`Token`] that has no safety requirements
pub trait Trivial: Token + Init {}

/// An [`Identifier`] who's tokens are guaranteed to *never* be owned by another
/// `Identifier`, even if this one is dropped
pub unsafe trait OneShotIdentifier: Identifier {}

/// 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 token that this identifier recognizes, which you can use to mark
/// other types as logically owned by the identifier. No other identifier will recognize
/// tokens made be a different identifier while both identifiers are live.
///
/// # Safety
///
/// * `ident.owns(&token)` must return true for any `token` returned
///     from `ident.token()` regardless of when the token was created.
/// * If two tokens compare equal, then `Identifier::owns` must act the
///     same for both of them
///     * i.e. it must return false for both tokens, or it must return
///         true for both tokens
/// * Two instances of `Identifier` must *never* return true for the same
///     token if either the two identifier or the tokens they generate can
///     both exist on the same thread.
pub unsafe trait Identifier {
    /// The tokens that this `Identifier` generates
    type Token: Token;

    #[inline]
    /// Check if this token was created by this identifier
    fn owns_token(&self, token: &Self::Token) -> bool { self.token() == *token }

    /// Create a new token
    fn token(&self) -> Self::Token;
}

unsafe impl<I: ?Sized + Identifier> Identifier for &mut I {
    type Token = I::Token;

    fn owns_token(&self, token: &Self::Token) -> bool { I::owns_token(self, token) }

    fn token(&self) -> Self::Token { I::token(self) }
}

#[cfg(feature = "alloc")]
unsafe impl<I: ?Sized + Identifier> Identifier for std::boxed::Box<I> {
    type Token = I::Token;

    fn owns_token(&self, token: &Self::Token) -> bool { I::owns_token(self, token) }

    fn token(&self) -> Self::Token { I::token(self) }
}

#[cfg(feature = "alloc")]
unsafe impl<I: ?Sized + OneShotIdentifier> OneShotIdentifier for std::boxed::Box<I> {}