singleton_cell/
lib.rs

1#![doc(html_root_url = "https://docs.rs/singleton-cell/0.3.1")]
2#![no_std]
3
4use core::cell::UnsafeCell;
5use core::marker::PhantomData;
6use core::mem;
7pub use singleton_trait::{Singleton, Exists, Erased};
8
9/**
10 * Macro-only code which must be public
11 */
12pub mod internal {
13    pub use paste;
14}
15
16/**
17 * SCell, or SingletonCell provides an interface of a
18 * Ghost Cell, where the Key is allowed to be any singleton,
19 * rather than a particular token type.
20 *
21 * As a result, the uniqueness for the key can be provided
22 * by any means, and the key type / resulting cell may also
23 * be 'static for long-lived data structures
24 */
25#[repr(transparent)]
26pub struct SCell<Key: ?Sized, T: ?Sized> {
27    _phantom: PhantomData<fn(Key)>,
28    inner: UnsafeCell<T>,
29}
30/**
31 * A more verbose alias for SCell
32 */
33pub type SingletonCell<Key, T> = SCell<Key, T>;
34/**
35 * An owned SCell is equivalent to its underlying value,
36 * and can be converted between them, so SCell<Key, T> is Send
37 * if and only if T is Send
38 */
39unsafe impl<Key, T: Send> Send for SCell<Key, T> {}
40
41/**
42 * A shared reference to SCell can access the underlying value
43 * both via shared reference, and via mutable reference,
44 * so it can be Sync only if T is both Sync and Send.
45 *
46 * SCell does not otherwise put any constraints on Sync
47 * since all shared usages must use references to the Key,
48 * which must be sent between threads as normal.
49 */
50unsafe impl<Key, T: Send + Sync> Sync for SCell<Key, T> {}
51
52impl<Key: ?Sized, T: ?Sized> SCell<Key, T> {
53    /**
54     * Convert a unique reference to a value to a unique reference
55     * to this cell type. These two types are equivalent when
56     * accessed uniquely.
57     */
58    #[inline(always)]
59    pub fn from_mut(t: &mut T) -> &mut Self {
60        // Safety:
61        // * The representations are transparent down to T
62        // * unique access to T enables unique access to self
63        unsafe { &mut *(t as *mut T as *mut Self) }
64    }
65
66    /**
67     * Uniquely borrow this cell in order to access T mutably.
68     *
69     * This requires unique access to self, rather than using
70     * a key. For shared access, see the `borrow_mut` method
71     * instead.
72     *
73     * Because this requires unique access to self, and all
74     * other borrows require at least a shared reference,
75     * unique access to the underlying data is safe.
76     */
77    #[inline(always)]
78    pub fn get_mut(&mut self) -> &mut T {
79        self.inner.get_mut()
80    }
81
82    /**
83     * Get a raw pointer to this cell's data.
84     */
85    #[inline(always)]
86    pub fn as_ptr(&self) -> *mut T {
87        self.inner.get()
88    }
89}
90
91impl<Key: ?Sized, T> SCell<Key, T> {
92    /**
93     * Construct a new SCell from underlying data.
94     *
95     * See also `SCell::from_mut` which can be used when the
96     * usage of SCell is only within the scope of mutable
97     * borrows of the data.
98     */
99    #[inline(always)]
100    pub fn new(t: T) -> Self {
101        SCell {
102            inner: UnsafeCell::new(t),
103            _phantom: PhantomData,
104        }
105    }
106
107    /**
108     * Destruct the SCell and access the inner data.
109     *
110     * This requires ownership of the SCell and hence guarantees
111     * no simultaneous access.
112     */
113    #[inline(always)]
114    pub fn into_inner(self) -> T {
115        self.inner.into_inner()
116    }
117}
118
119impl<Key: ?Sized, T> SCell<Key, [T]> {
120    /**
121     * Returns a slice of cells from a cell of a slice.
122     */
123    #[inline(always)]
124    pub fn as_slice_of_cells(&self) -> &[SCell<Key, T>] {
125        // Safety:
126        // * The representations are identical
127        // * the output lifetime is constrained to the input lifetime
128        unsafe { &*(self.as_ptr() as *mut [SCell<Key, T>]) }
129    }
130}
131
132impl<Key: Singleton + ?Sized, T: ?Sized> SCell<Key, T> {
133    /**
134     * Borrow the data underlying this cell, using a reference to
135     * the singleton Key type.
136     *
137     * This is safe because any mutable borrow must either come
138     * from a mutable reference to this cell, or a mutable reference
139     * to the key, which cannot exist since this takes a shared
140     * borrow of both this cell and the key.
141     */
142    #[inline(always)]
143    pub fn borrow<'a>(&'a self, _: impl Exists<&'a Key>) -> &'a T
144    where
145        Key: 'a,
146    {
147        // Safety:
148        // By the contract for Singleton & Erased
149        // the unique value of Key is borrowed immutably for 'a
150        //
151        // * Every borrow to T requires either &mut self or a &Key/&mut Key
152        //   so the only other borrow available would be this method taking &Key,
153        //   which is compatible with the shared reference output
154        unsafe { &*self.inner.get() }
155    }
156
157    /**
158     * Mutably borrow the data underlying this cell,
159     * using a mutable reference to the singleton Key type.
160     *
161     * This is safe because it requires a unique borrow of the key,
162     * and a shared borrow of self, which prevents all other borrows
163     * into the data.
164     */
165    #[allow(clippy::mut_from_ref)] // Clippy can't see through the Exists
166    #[inline(always)]
167    pub fn borrow_mut<'a>(&'a self, _: impl Exists<&'a mut Key>) -> &'a mut T
168    where
169        Key: 'a,
170    {
171        // Safety:
172        // By the contract for Singleton & Erased
173        // the unique value of Key is borrowed mutably for 'a
174        //
175        // * Every borrow to T requires either &mut self or a &Key/&mut Key
176        //   which are excluded by the borrows in the signature
177        unsafe { &mut *self.inner.get() }
178    }
179}
180
181impl<Key: Singleton + ?Sized, T> SCell<Key, T> {
182    /**
183     * Replace the value behind this cell with a new one.
184     *
185     * This mutates the data and hence requires unique access to the key
186     * to ensure that no borrows are invalidated.
187     */
188    #[inline(always)]
189    pub fn replace<'a>(&'a self, value: T, token: impl Exists<&'a mut Key>) -> T
190    where
191        Key: 'a,
192    {
193        mem::replace(self.borrow_mut(token), value)
194    }
195
196    /**
197     * Replace the value behind this cell with the default one.
198     *
199     * This mutates the data and so requires unique access to the key
200     * to ensure that no borrows are invalidated.
201     */
202    #[inline(always)]
203    pub fn take<'a>(&'a self, token: impl Exists<&'a mut Key>) -> T
204    where
205        Key: 'a,
206        T: Default,
207    {
208        mem::take(self.borrow_mut(token))
209    }
210}
211
212/**
213 * A temporary singleton token created by the with_token function.
214 *
215 * See the with_token function for details.
216 */
217pub struct Token<'brand>(PhantomData<fn(&'brand ()) -> &'brand ()>);
218// SAFETY:
219// We only construct this with a unique, invariant brand in with_token
220// For everything else, we just defer to ghost cell's GhostToken
221unsafe impl<'brand> Singleton for Token<'brand> {}
222unsafe impl<'brand> Send for Token<'brand> {}
223unsafe impl<'brand> Sync for Token<'brand> {}
224
225/**
226 * Generate a local token type which is guaranteed to be a singleton via
227 * a unique lifetime brand. SCells can be created within this scope via
228 * SCell::new or SCell::from_mut and used via this token.
229 *
230 * Because the 'brand lifetime is unique to this scope, neither this
231 * token, nor any SCell's created with it as the key may escape the scope.
232 *
233 * It is most likely useful when cells are created with SCell::from_mut,
234 * which means that cells can be used for data structures that don't
235 * mention SCell or the 'brand.
236 *
237 * For a token type which does not have this restriction, see new_singleton
238 * for one implementation.
239 *
240 * ```
241 *  use singleton_cell::*;
242 *
243 *  let mut x = 0;
244 *  with_token(|mut tok| {
245 *      let cell_borrow = &*SCell::from_mut(&mut x);
246 *      *cell_borrow.borrow_mut(&mut tok) += 2;
247 *
248 *      let cell_one = SCell::new(0);
249 *      *cell_one.borrow_mut(&mut tok) += 1;
250 *      cell_one.into_inner()
251 *  });
252 *  assert_eq!(2, x);
253 * ```
254 */
255#[inline(always)]
256pub fn with_token<R>(f: impl for<'brand> FnOnce(Token<'brand>) -> R) -> R {
257    // SAFETY: 'brand can't leak as f is polymorphic over it
258    let token = Token(PhantomData);
259    f(token)
260}
261
262///
263/// Generates a new global singleton type with a fallible constructor.
264/// This is intended for cases where a single instance is created early
265/// in the program and passed throughout.
266///
267/// This is one way to create a Singleton which is 'static and Send/Sync
268///
269/// ```
270/// #[macro_use] extern crate singleton_cell;
271/// new_singleton!(pub Token);
272/// fn main() {
273///     let tok = Token::new().expect("Main called only once");
274///
275///     // possibly combine with Erased borrows
276///     use singleton_trait::Erased;
277///     let tok = Erased::new(tok);
278///
279/// }
280///
281/// ```
282///
283/// This method will return Some the first time it is called, and None
284/// any time thereafter. This does not establish any ordering between
285/// multiple threads if they access at the same time.
286///
287// Credit to Yandros for significant help with the idea / designing
288// the original macro using std::sync::Once instead of AtomicBool.
289//
290// We use AtomicBool here instead to remain no-std and simplify the
291// resulting code given that we don't need most features of Once.
292#[macro_export]
293macro_rules! new_singleton {
294    ( $pub:vis $Name:ident ) => {
295        $crate::internal::paste::paste! {
296            $pub use [< __ $Name _help__ >]::$Name;
297            #[allow(nonstandard_style)]
298            mod [< __ $Name _help__ >] {
299
300                pub
301                struct $Name(());
302
303                impl $Name {
304
305                    pub
306                    fn new () -> Option<Self> {
307                        let first_run = {
308                            static ONCE: ::core::sync::atomic::AtomicBool =
309                                ::core::sync::atomic::AtomicBool::new(false);
310                            &ONCE
311                        };
312                        if first_run
313                            // We don't need any ordering guarantees between accesses, only atomicity
314                            .compare_exchange(false, true,
315                                ::core::sync::atomic::Ordering::Relaxed,
316                                ::core::sync::atomic::Ordering::Relaxed)
317                            .is_ok()
318                        {
319                            // Safety:
320                            // * ONCE is a static, hence it is a single memory location which is false at
321                            // program start.
322                            // * The program start happens before all reads
323                            // * Only one CAS from false to true can succeed since it will never become
324                            // false again
325                            Some( $Name(()) )
326                        } else {
327                            None
328                        }
329                    }
330
331                    #[inline(always)]
332                    pub
333                    fn new_erased() -> Option<$crate::Erased<Self>> {
334                        Self::new().map(|x| $crate::Erased::new(x))
335                    }
336                }
337
338                // Safety: construction is guarded by the CAS on a static above
339                // So only one instance can be created per program
340                unsafe
341                impl $crate::Singleton for $Name {}
342            }
343        }
344    };
345}
346
347#[cfg(test)]
348mod tests {
349    extern crate alloc;
350    extern crate std;
351    use crate as singleton_cell;
352    use super::*;
353    use alloc::string::String;
354
355    #[test]
356    fn ghost_trivial() {
357        let mut i = String::new();
358
359        with_token(|mut tok| {
360            let i = SCell::from_mut(&mut i);
361            i.get_mut().push_str("A");
362
363            i.borrow_mut(&mut tok).push_str("B");
364            let first = i.borrow(&tok).clone();
365
366            i.borrow_mut(&mut tok).push_str("C");
367            let last = i.borrow(&tok);
368
369            assert_eq!("AB", &*first);
370            assert_eq!("ABC", &*last);
371        });
372
373        assert_eq!("ABC", &*i);
374    }
375
376    #[inline(never)]
377    fn write_to<Key: Singleton>(sc: &SCell<Key, String>, k: &mut Key) {
378        sc.borrow_mut(k).push_str("!");
379    }
380
381    #[test]
382    fn ghost_read_after_write() {
383        let result = with_token(|mut tok| {
384            let mut s = String::from("A");
385            let s = SCell::from_mut(&mut s);
386
387            let borrow = &*s;
388            write_to(&*s, &mut tok);
389            write_to(&*s, &mut tok);
390
391            borrow.borrow(&tok).clone()
392        });
393        assert_eq!("A!!", &*result);
394    }
395
396    #[test]
397    fn local_type_round_trip() {
398        let local = ();
399        let mut tok = {
400            struct Local<'a>(&'a ());
401            unsafe impl<'a> Singleton for Local<'a> {}
402            Local(&local)
403        };
404
405        let mut s = String::from("A");
406        let s_mut = &mut s;
407        let s_cell = SCell::from_mut(s_mut);
408        let s_cell2 = &*s_cell;
409
410        write_to(s_cell2, &mut tok);
411
412        assert_eq!("A!", s_cell.borrow_mut(&mut tok));
413        write_to(s_cell2, &mut tok);
414        assert_eq!("A!!", s_cell.borrow(&tok));
415        assert_eq!("A!!", s_cell.get_mut());
416        s_cell.get_mut().push_str("C");
417        assert_eq!("A!!C", s_mut);
418    }
419
420    #[test]
421    fn global_singleton_unique() {
422        new_singleton!(pub A);
423        let _ = A::new();
424        assert!(A::new().is_none(), "Second call to A::new() should be None");
425    }
426
427    #[test]
428    fn global_singleton_distinct() {
429        new_singleton!(pub A);
430        new_singleton!(pub B);
431        let a: Option<A> = A::new();
432        let b: Option<B> = B::new();
433
434        assert!(a.is_some(), "A should be Some");
435        assert!(b.is_some(), "B should be Some");
436    }
437}