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}