1use crate::registry::RegistryInterface;
2use std::{
3 marker::PhantomData,
4 mem::MaybeUninit,
5 ops::Deref,
6 sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard, Weak},
7};
8
9pub type EntryId = u32;
11
12pub struct Entry<T = ()> {
15 iface: Weak<RwLock<dyn RegistryInterface + 'static>>,
16 id: EntryId,
17 phantom: PhantomData<T>,
18}
19
20impl std::fmt::Debug for Entry {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 write!(f, "E{:?}", self.id)
23 }
24}
25
26impl<T> Entry<T>
27where
28 T: Send + Sync,
29{
30 pub(crate) fn new(iface: Weak<RwLock<dyn RegistryInterface>>, id: EntryId) -> Self {
31 Self {
32 iface,
33 id,
34 phantom: PhantomData,
35 }
36 }
37
38 pub fn as_generic(self) -> Entry {
41 let maybe_uninit = MaybeUninit::new(self);
42 let ptr = maybe_uninit.as_ptr();
43 unsafe {
44 Entry {
46 iface: std::ptr::read(&(*ptr).iface),
47 id: std::ptr::read(&(*ptr).id),
48 phantom: PhantomData,
49 }
50 }
51 }
52
53 pub fn write(&self) -> Option<EntryWriteGuard<T>> {
58 let registry = self.iface.upgrade()?;
59 let ptr = self.iface.as_ptr();
60 let reference = unsafe { &*ptr };
64 Some(EntryWriteGuard::<T> {
65 _registry: registry,
66 guard: reference.write().unwrap(),
67 entry_id: self.id,
68 phantom: PhantomData,
69 })
70 }
71
72 pub fn read(&self) -> Option<EntryReadGuard<T>> {
77 let registry = self.iface.upgrade()?;
78 let ptr = self.iface.as_ptr();
79 let reference = unsafe { &*ptr };
83 Some(EntryReadGuard::<T> {
84 _registry: registry,
85 guard: reference.read().unwrap(),
86 entry_id: self.id,
87 phantom: PhantomData,
88 })
89 }
90
91 pub fn get_id(&self) -> EntryId {
93 self.id
94 }
95
96 pub unsafe fn leak(self) {
99 std::mem::forget(self);
100 }
101}
102
103impl<T> Drop for Entry<T> {
104 #[inline(always)]
105 fn drop(&mut self) {
106 if let Some(arc) = self.iface.upgrade() {
107 if let Ok(mut guard) = arc.write() {
108 guard.remove(self.id);
109 }
110 }
111 }
112}
113
114pub struct EntryWriteGuard<'a, T> {
116 _registry: Arc<RwLock<dyn RegistryInterface>>,
117 guard: RwLockWriteGuard<'a, dyn RegistryInterface + 'static>,
118 entry_id: EntryId,
119 phantom: PhantomData<T>,
120}
121
122impl<T: 'static> EntryWriteGuard<'_, T> {
123 pub fn get(&self) -> &T {
125 self.guard
126 .get(self.entry_id)
127 .expect("Entry not found in the Registry")
128 .downcast_ref::<T>()
129 .expect("Failed to downcast Entry")
130 }
131
132 pub fn get_mut(&mut self) -> &mut T {
134 self.guard
135 .get_mut(self.entry_id)
136 .expect("Entry not found in the Registry")
137 .downcast_mut::<T>()
138 .expect("Failed to downcast Entry")
139 }
140}
141
142pub struct EntryReadGuard<'a, T> {
144 _registry: Arc<RwLock<dyn RegistryInterface>>,
145 guard: RwLockReadGuard<'a, dyn RegistryInterface + 'static>,
146 entry_id: EntryId,
147 phantom: PhantomData<T>,
148}
149
150impl<'a, T: 'static> Deref for EntryReadGuard<'a, T> {
151 type Target = T;
152
153 fn deref(&self) -> &Self::Target {
154 self.guard
155 .get(self.entry_id)
156 .expect("Entry not found in the Registry")
157 .downcast_ref::<T>()
158 .expect("Failed to downcast Entry")
159 }
160}
161
162impl<T: 'static> EntryReadGuard<'_, T> {
163 pub fn get(&self) -> &T {
165 self.guard
166 .get(self.entry_id)
167 .expect("Entry not found in the Registry")
168 .downcast_ref::<T>()
169 .expect("Failed to downcast Entry")
170 }
171}
172
173#[cfg(test)]
174mod test {
175 use super::*;
176
177 #[test]
178 fn test() {
179 assert_eq!(size_of::<Entry>(), 24);
180 assert_eq!(size_of::<EntryReadGuard<()>>(), 48);
181 }
182}