Skip to main content

starnix_uapi/
arc_key.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use fuchsia_rcu::RcuDroppable;
6use ref_cast::RefCast;
7use std::borrow::Borrow;
8use std::cmp::Ordering;
9use std::hash::{Hash, Hasher};
10use std::ops::Deref;
11use std::sync::{Arc, Weak};
12
13/// A wrapper around Arc with Hash implemented based on Arc::as_ptr.
14#[derive(RefCast, RcuDroppable)]
15#[repr(transparent)]
16pub struct ArcKey<T>(pub Arc<T>);
17impl<T> PartialEq for ArcKey<T> {
18    fn eq(&self, other: &Self) -> bool {
19        Arc::ptr_eq(&self.0, &other.0)
20    }
21}
22impl<T> Eq for ArcKey<T> {}
23impl<T> PartialOrd for ArcKey<T> {
24    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
25        Some(self.cmp(other))
26    }
27}
28impl<T> Ord for ArcKey<T> {
29    fn cmp(&self, other: &Self) -> Ordering {
30        Arc::as_ptr(&self.0).cmp(&Arc::as_ptr(&other.0))
31    }
32}
33impl<T> Hash for ArcKey<T> {
34    fn hash<H: Hasher>(&self, state: &mut H) {
35        Arc::as_ptr(&self.0).hash(state);
36    }
37}
38impl<T> Clone for ArcKey<T> {
39    fn clone(&self) -> Self {
40        Self(Arc::clone(&self.0))
41    }
42}
43impl<T> Deref for ArcKey<T> {
44    type Target = Arc<T>;
45    fn deref(&self) -> &Self::Target {
46        &self.0
47    }
48}
49
50impl<T: std::fmt::Debug> std::fmt::Debug for ArcKey<T> {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        self.0.fmt(f)
53    }
54}
55
56/// A wrapper around Weak with Hash implemented based on Weak::as_ptr.
57pub struct WeakKey<T>(pub Weak<T>, PtrKey<T>);
58impl<T> WeakKey<T> {
59    pub fn from(arc: &Arc<T>) -> Self {
60        Self(Arc::downgrade(arc), Arc::as_ptr(arc).into())
61    }
62}
63impl<T> Clone for WeakKey<T> {
64    fn clone(&self) -> Self {
65        Self(self.0.clone(), self.1.clone())
66    }
67}
68impl<T> PartialEq<Weak<T>> for WeakKey<T> {
69    fn eq(&self, other: &Weak<T>) -> bool {
70        Weak::ptr_eq(&self.0, other)
71    }
72}
73impl<T> PartialEq for WeakKey<T> {
74    fn eq(&self, other: &Self) -> bool {
75        *self == other.0
76    }
77}
78impl<T> Eq for WeakKey<T> {}
79impl<T> PartialOrd for WeakKey<T> {
80    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
81        Some(self.cmp(other))
82    }
83}
84impl<T> Ord for WeakKey<T> {
85    fn cmp(&self, other: &Self) -> Ordering {
86        Weak::as_ptr(&self.0).cmp(&Weak::as_ptr(&other.0))
87    }
88}
89impl<T> Hash for WeakKey<T> {
90    fn hash<H: Hasher>(&self, state: &mut H) {
91        Weak::as_ptr(&self.0).hash(state);
92    }
93}
94impl<T> Borrow<PtrKey<T>> for WeakKey<T> {
95    fn borrow(&self) -> &PtrKey<T> {
96        &self.1
97    }
98}
99
100impl<T: std::fmt::Debug> std::fmt::Debug for WeakKey<T> {
101    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102        self.0.fmt(f)
103    }
104}
105
106pub struct PtrKey<T>(*const T);
107impl<T> From<*const T> for PtrKey<T> {
108    fn from(ptr: *const T) -> Self {
109        Self(ptr)
110    }
111}
112impl<T> From<&T> for PtrKey<T> {
113    fn from(r: &T) -> Self {
114        Self(r as *const T)
115    }
116}
117impl<T> From<&Arc<T>> for PtrKey<T> {
118    fn from(arc: &Arc<T>) -> Self {
119        Self(Arc::as_ptr(arc))
120    }
121}
122impl<T> From<&ArcKey<T>> for PtrKey<T> {
123    fn from(arc_key: &ArcKey<T>) -> Self {
124        Self(Arc::as_ptr(&arc_key.0))
125    }
126}
127impl<T> Clone for PtrKey<T> {
128    fn clone(&self) -> Self {
129        Self(self.0)
130    }
131}
132impl<T> PartialEq for PtrKey<T> {
133    fn eq(&self, other: &Self) -> bool {
134        self.0 == other.0
135    }
136}
137impl<T> Eq for PtrKey<T> {}
138impl<T> Hash for PtrKey<T> {
139    fn hash<H: Hasher>(&self, state: &mut H) {
140        self.0.hash(state)
141    }
142}
143#[allow(clippy::undocumented_unsafe_blocks, reason = "Force documented unsafe blocks in Starnix")]
144unsafe impl<T> Sync for PtrKey<T> {}
145#[allow(clippy::undocumented_unsafe_blocks, reason = "Force documented unsafe blocks in Starnix")]
146unsafe impl<T> Send for PtrKey<T> {}
147
148impl<T: std::fmt::Debug> std::fmt::Debug for PtrKey<T> {
149    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150        self.0.fmt(f)
151    }
152}
153
154// SAFETY: WeakKey wraps Weak<T>, which only decrements the weak refcount on drop without dropping T.
155unsafe impl<T: Send + Sync + 'static> RcuDroppable for WeakKey<T> {}
156// SAFETY: PtrKey contains a raw pointer and has no drop side effects.
157unsafe impl<T: 'static> RcuDroppable for PtrKey<T> {}