1pub unsafe trait RcuDroppable: Send + 'static {}
11
12macro_rules! impl_rcu_droppable {
13 ($($t:ty),* $(,)?) => {
14 $(
15 unsafe impl RcuDroppable for $t {}
18 )*
19 };
20}
21
22impl_rcu_droppable!(
23 (),
24 bool,
25 char,
26 u8,
27 u16,
28 u32,
29 u64,
30 u128,
31 usize,
32 i8,
33 i16,
34 i32,
35 i64,
36 i128,
37 isize,
38 f32,
39 f64,
40 String,
41 str,
42 bstr::BString,
43 bstr::BStr,
44 fuchsia_runtime::UtcTimeline,
45 fuchsia_trace::Id,
46 shared_buffer::SharedBuffer,
47 std::collections::hash_map::RandomState,
48 std::num::NonZeroU8,
49 std::num::NonZeroU16,
50 std::num::NonZeroU32,
51 std::num::NonZeroU64,
52 std::num::NonZeroU128,
53 std::num::NonZeroUsize,
54 std::num::NonZeroI8,
55 std::num::NonZeroI16,
56 std::num::NonZeroI32,
57 std::num::NonZeroI64,
58 std::num::NonZeroI128,
59 std::num::NonZeroIsize,
60 std::sync::atomic::AtomicBool,
61 std::sync::atomic::AtomicI8,
62 std::sync::atomic::AtomicI16,
63 std::sync::atomic::AtomicI32,
64 std::sync::atomic::AtomicI64,
65 std::sync::atomic::AtomicIsize,
66 std::sync::atomic::AtomicU8,
67 std::sync::atomic::AtomicU16,
68 std::sync::atomic::AtomicU32,
69 std::sync::atomic::AtomicU64,
70 std::sync::atomic::AtomicUsize,
71 std::ops::RangeFull,
72 std::time::Duration,
73 std::time::Instant,
74 zx::BootTimeline,
75 zx::Koid,
76 zx::MonotonicTimeline,
77 zx::Rights,
78 zx::Vmo,
79);
80
81unsafe impl<T: ?Sized + Sync + 'static> RcuDroppable for &'static T {}
83unsafe impl<H: 'static> RcuDroppable for std::hash::BuildHasherDefault<H> {}
85unsafe impl<T: ?Sized + Send + 'static> RcuDroppable for std::marker::PhantomData<T> {}
87unsafe impl<T: RcuDroppable> RcuDroppable for Option<T> {}
89unsafe impl<T: RcuDroppable, E: RcuDroppable> RcuDroppable for Result<T, E> {}
91unsafe impl<T: ?Sized + RcuDroppable> RcuDroppable for Box<T> {}
93unsafe impl<T: ?Sized + RcuDroppable + Sync> RcuDroppable for std::sync::Arc<T> {}
95unsafe impl<T: RcuDroppable + Sync> RcuDroppable for std::sync::OnceLock<T> {}
97unsafe impl<T: ?Sized + Send + Sync + 'static> RcuDroppable for std::sync::Weak<T> {}
99unsafe impl<T: RcuDroppable> RcuDroppable for Vec<T> {}
101unsafe impl<K: RcuDroppable, V: RcuDroppable, S: RcuDroppable> RcuDroppable
103 for std::collections::HashMap<K, V, S>
104{
105}
106unsafe impl<T: RcuDroppable, const N: usize> RcuDroppable for [T; N] {}
108unsafe impl<T: RcuDroppable> RcuDroppable for [T] {}
110unsafe impl<T: Send + 'static> RcuDroppable for std::sync::mpsc::Sender<T> {}
112unsafe impl<T: Send + 'static> RcuDroppable for std::sync::mpsc::SyncSender<T> {}
114unsafe impl<T: Send + 'static> RcuDroppable for futures::channel::mpsc::Sender<T> {}
116unsafe impl<T: Send + 'static> RcuDroppable for futures::channel::mpsc::UnboundedSender<T> {}
118unsafe impl<T: Send + 'static> RcuDroppable for futures::channel::oneshot::Sender<T> {}
120unsafe impl<T: 'static> RcuDroppable for std::sync::atomic::AtomicPtr<T> {}
122unsafe impl<T: 'static> RcuDroppable for crate::rcu_ptr::RcuPtr<T> {}
124
125unsafe impl<T: RcuDroppable> RcuDroppable for std::ops::Range<T> {}
128unsafe impl<T: RcuDroppable> RcuDroppable for std::ops::RangeFrom<T> {}
130unsafe impl<T: RcuDroppable> RcuDroppable for std::ops::RangeInclusive<T> {}
132unsafe impl<T: RcuDroppable> RcuDroppable for std::ops::RangeTo<T> {}
134unsafe impl<T: RcuDroppable> RcuDroppable for std::ops::RangeToInclusive<T> {}
136
137unsafe impl<T: RcuDroppable + Sync> RcuDroppable for crate::RcuDroppableArc<T> {}
140unsafe impl<T: RcuDroppable + Sync> RcuDroppable for crate::RcuBox<T> {}
142unsafe impl<T: RcuDroppable + Sync> RcuDroppable for crate::RcuOptionArc<T> {}
144unsafe impl<T: RcuDroppable + Sync> RcuDroppable for crate::RcuOptionBox<T> {}
146unsafe impl<T: Send + Sync + 'static> RcuDroppable for crate::RcuWeak<T> {}
148unsafe impl<T: RcuDroppable + Sync> RcuDroppable for crate::RcuArc<T> {}
150unsafe impl<T: ?Sized + RcuDroppable> RcuDroppable for fuchsia_sync::Mutex<T> {}
153unsafe impl<T: ?Sized + RcuDroppable> RcuDroppable for fuchsia_sync::RwLock<T> {}
155unsafe impl RcuDroppable for fuchsia_sync::Completion {}
157
158unsafe impl<T: Send + 'static, U: Send + 'static> RcuDroppable for zx::Clock<T, U> {}
162
163unsafe impl<T: Send + 'static, U: Send + 'static> RcuDroppable for zx::Instant<T, U> {}
166
167unsafe impl<A: RcuDroppable> RcuDroppable for (A,) {}
170unsafe impl<A: RcuDroppable, B: RcuDroppable> RcuDroppable for (A, B) {}
172unsafe impl<A: RcuDroppable, B: RcuDroppable, C: RcuDroppable> RcuDroppable for (A, B, C) {}
174unsafe impl<A: RcuDroppable, B: RcuDroppable, C: RcuDroppable, D: RcuDroppable> RcuDroppable
176 for (A, B, C, D)
177{
178}
179
180#[expect(dead_code)]
183#[cfg(test)]
184mod tests {
185 use crate::RcuDroppable;
186
187 #[derive(RcuDroppable)]
188 struct UnitStruct;
189
190 #[derive(RcuDroppable)]
191 struct TupleStruct(u32, String);
192
193 #[derive(RcuDroppable)]
194 struct NamedStruct<T> {
195 foo: T,
196 bar: Vec<u8>,
197 }
198
199 #[derive(RcuDroppable)]
200 enum TestEnum<T> {
201 A(T),
202 B { val: String },
203 C,
204 }
205
206 #[derive(RcuDroppable)]
207 struct ComplexStruct {
208 atomic: std::sync::atomic::AtomicUsize,
209 range: std::ops::Range<usize>,
210 non_zero: std::num::NonZeroU32,
211 mutex: fuchsia_sync::Mutex<u32>,
212 rwlock: fuchsia_sync::RwLock<String>,
213 rcu_arc: crate::RcuArc<u32>,
214 weak: std::sync::Weak<u32>,
215 hash_map: std::collections::HashMap<u32, String>,
216 }
217
218 fn assert_rcu_droppable<T: super::RcuDroppable>() {}
219
220 #[test]
221 fn test_derive_rcu_droppable() {
222 assert_rcu_droppable::<UnitStruct>();
223 assert_rcu_droppable::<TupleStruct>();
224 assert_rcu_droppable::<NamedStruct<u32>>();
225 assert_rcu_droppable::<TestEnum<u64>>();
226 assert_rcu_droppable::<ComplexStruct>();
227 assert_rcu_droppable::<bstr::BString>();
228 assert_rcu_droppable::<fuchsia_sync::Completion>();
229 assert_rcu_droppable::<futures::channel::mpsc::UnboundedSender<u32>>();
230 }
231}