1use once_cell::sync::OnceCell as Sync_OnceCell;
2use once_cell::unsync::OnceCell as Unsync_OnceCell;
3
4use crate::unsafe_once_self_cell::DependentInner;
5
6pub mod unsafe_once_self_cell;
7
8pub trait OnceCellCompatible<T> {
9 fn new() -> Self;
10 fn get(&self) -> Option<&T>;
11 fn get_or_init<F>(&self, f: F) -> &T
12 where
13 F: FnOnce() -> T;
14 fn take(&mut self) -> Option<T>;
15}
16
17#[derive(Debug)]
20pub struct UnsyncOnceCell(Unsync_OnceCell<DependentInner>);
21
22impl crate::OnceCellCompatible<DependentInner> for UnsyncOnceCell {
23 fn new() -> Self {
24 UnsyncOnceCell(Unsync_OnceCell::new())
25 }
26 fn get(&self) -> Option<&DependentInner> {
27 self.0.get()
28 }
29 fn get_or_init<F>(&self, f: F) -> &DependentInner
30 where
31 F: FnOnce() -> DependentInner,
32 {
33 self.0.get_or_init(f)
34 }
35 fn take(&mut self) -> Option<DependentInner> {
36 self.0.take()
37 }
38}
39
40#[macro_export]
41macro_rules! unsync_once_self_cell {
42 ($StructName:ident, $Owner:ty, $Dependent:ty $(, $StructMeta:meta)* $(,)?) => {
43 $(#[$StructMeta])*
44 struct $StructName {
45 unsafe_self_cell: ::once_self_cell::unsafe_once_self_cell::UnsafeOnceSelfCell<
46 $Owner,
47 ::once_self_cell::UnsyncOnceCell,
48 >,
49 }
50
51 impl $StructName {
52 pub fn new(owner: $Owner) -> Self {
53 Self {
54 unsafe_self_cell: unsafe {
55 ::once_self_cell::unsafe_once_self_cell::UnsafeOnceSelfCell::new(owner)
56 },
57 }
58 }
59
60 pub fn get_owner<'a>(&'a self) -> &'a $Owner {
61 unsafe { self.unsafe_self_cell.get_owner() }
62 }
63
64 pub fn get_or_init_dependent<'a>(&'a self) -> &'a $Dependent {
65 unsafe {
66 self.unsafe_self_cell
67 .get_or_init_dependent(|owner_ref| owner_ref.into())
68 }
69 }
70
71 pub fn dependent_is_none(&self) -> bool {
72 self.unsafe_self_cell.dependent_is_none()
73 }
74 }
75
76 impl Drop for $StructName {
77 fn drop(&mut self) {
78 unsafe {
79 self.unsafe_self_cell.drop_dependent::<$Dependent>();
80 }
81 }
82 }
83 };
84}
85
86#[derive(Debug)]
87pub struct SyncOnceCell(Sync_OnceCell<DependentInner>);
88
89impl crate::OnceCellCompatible<DependentInner> for SyncOnceCell {
90 fn new() -> Self {
91 SyncOnceCell(Sync_OnceCell::new())
92 }
93 fn get(&self) -> Option<&DependentInner> {
94 self.0.get()
95 }
96 fn get_or_init<F>(&self, f: F) -> &DependentInner
97 where
98 F: FnOnce() -> DependentInner,
99 {
100 self.0.get_or_init(f)
101 }
102 fn take(&mut self) -> Option<DependentInner> {
103 self.0.take()
104 }
105}
106
107unsafe impl Send for SyncOnceCell {}
120unsafe impl Sync for SyncOnceCell {}
121
122#[macro_export]
123macro_rules! sync_once_self_cell {
124 ($StructName:ident, $Owner:ty, $Dependent:ty $(, $StructMeta:meta)* $(,)?) => {
125 $(#[$StructMeta])*
126 struct $StructName {
127 unsafe_self_cell: ::once_self_cell::unsafe_once_self_cell::UnsafeOnceSelfCell<
128 $Owner,
129 ::once_self_cell::SyncOnceCell,
130 >,
131 }
132
133 impl $StructName {
134 pub fn new(owner: $Owner) -> Self {
135 Self {
136 unsafe_self_cell: unsafe {
137 ::once_self_cell::unsafe_once_self_cell::UnsafeOnceSelfCell::new(owner)
138 },
139 }
140 }
141
142 pub fn get_owner<'a>(&'a self) -> &'a $Owner {
143 unsafe { self.unsafe_self_cell.get_owner() }
144 }
145
146 pub fn get_or_init_dependent<'a>(&'a self) -> &'a $Dependent {
147 unsafe {
148 self.unsafe_self_cell
149 .get_or_init_dependent(|owner_ref| owner_ref.into())
150 }
151 }
152
153 pub fn dependent_is_none(&self) -> bool {
154 self.unsafe_self_cell.dependent_is_none()
155 }
156 }
157
158 impl Drop for $StructName {
159 fn drop(&mut self) {
160 unsafe {
161 self.unsafe_self_cell.drop_dependent::<$Dependent>();
162 }
163 }
164 }
165 };
166}
167
168