Skip to main content

xiaoyong_value/sync/
permanent.rs

1//! Handle to a statically allocated data.
2
3use std::{
4    fmt,
5    mem,
6    ops::Deref,
7};
8
9/// Handle that mimics a `'static` reference.
10///
11/// **Thread Safety:** Can be used anywhere and does not produce any form of
12/// overhead.
13pub struct Permanent<T: 'static> {
14    inner: &'static T,
15}
16
17// Safety: Permanent<T> is Send/Sync if the underlying T is Sync.
18// Since we only provide &T access, T does not strictly need to be Send
19// for the handle to be Sync, but usually, we want T: Send + Sync.
20unsafe impl<T: Sync + 'static> Send for Permanent<T> {}
21unsafe impl<T: Sync + 'static> Sync for Permanent<T> {}
22
23impl<T: 'static> Permanent<T> {
24    /// Create a new instance.
25    pub fn new(value: Box<T>) -> Self {
26        let leaked = Box::leak(value);
27        Self {
28            inner: leaked
29        }
30    }
31
32    /// Drop the stored value.
33    ///
34    /// ## Safety
35    ///
36    /// The caller MUST ensure that:
37    /// - No other copies of this `Permanent<T>` (or any references derived from
38    ///   it) exist anywhere in the program.
39    /// - This function is called exactly once for the allocated memory.
40    pub unsafe fn drop_permanent(self) {
41        let ptr = self.inner as *const T as *mut T;
42        unsafe {
43            mem::drop(Box::from_raw(ptr));
44        }
45    }
46}
47
48impl<T: 'static> Clone for Permanent<T> {
49    fn clone(&self) -> Self {
50        *self
51    }
52}
53
54impl<T: 'static> Copy for Permanent<T> {}
55
56impl<T: 'static> Deref for Permanent<T> {
57    type Target = T;
58
59    #[inline(always)]
60    fn deref(&self) -> &Self::Target {
61        self.inner
62    }
63}
64
65impl<T: fmt::Debug + 'static> fmt::Debug for Permanent<T> {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        f.debug_struct("Permanent").field("inner", &self.inner).finish()
68    }
69}
70
71impl<T: fmt::Display + 'static> fmt::Display for Permanent<T> {
72    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73        fmt::Display::fmt(self.inner, f)
74    }
75}