registry_io/async_registry/guard.rs
1//! RAII async handler guard.
2//!
3//! Mirror of [`crate::HandlerGuard`] for [`AsyncRegistry`].
4//! Dropping the guard unregisters the async handler; holding a
5//! [`std::sync::Weak`] reference means a registry dropped before its guard
6//! still drops cleanly.
7
8use std::sync::Weak;
9
10use crate::HandlerId;
11
12use super::AsyncRegistry;
13
14/// RAII handle for a registered async handler.
15///
16/// # Examples
17///
18/// ```
19/// use std::sync::Arc;
20/// use registry_io::r#async::AsyncRegistry;
21///
22/// let registry = Arc::new(AsyncRegistry::<()>::new());
23/// assert!(registry.is_empty());
24///
25/// {
26/// let _guard = registry.register_guard(|_| async move {});
27/// assert_eq!(registry.handler_count(), 1);
28/// }
29/// assert!(registry.is_empty());
30/// ```
31#[must_use = "dropping the AsyncHandlerGuard immediately unregisters the handler; \
32 bind it to a name to keep the handler alive"]
33pub struct AsyncHandlerGuard<E: Send + Sync + 'static> {
34 id: HandlerId,
35 registry: Weak<AsyncRegistry<E>>,
36}
37
38impl<E: Send + Sync + 'static> AsyncHandlerGuard<E> {
39 /// Internal constructor used by `AsyncRegistry`.
40 pub(crate) fn new(id: HandlerId, registry: Weak<AsyncRegistry<E>>) -> Self {
41 Self { id, registry }
42 }
43
44 /// Returns the [`HandlerId`] of the underlying registration.
45 ///
46 /// # Examples
47 ///
48 /// ```
49 /// use std::sync::Arc;
50 /// use registry_io::r#async::AsyncRegistry;
51 ///
52 /// let registry = Arc::new(AsyncRegistry::<()>::new());
53 /// let guard = registry.register_guard(|_| async move {});
54 /// let id = guard.id();
55 /// drop(guard);
56 /// assert!(!registry.contains(id));
57 /// ```
58 #[inline]
59 #[must_use]
60 pub fn id(&self) -> HandlerId {
61 self.id
62 }
63
64 /// Consume the guard without unregistering the handler.
65 ///
66 /// # Examples
67 ///
68 /// ```
69 /// use std::sync::Arc;
70 /// use registry_io::r#async::AsyncRegistry;
71 ///
72 /// let registry = Arc::new(AsyncRegistry::<()>::new());
73 /// let guard = registry.register_guard(|_| async move {});
74 /// let id = guard.id();
75 /// guard.forget();
76 /// assert!(registry.contains(id));
77 /// assert!(registry.unregister(id));
78 /// ```
79 pub fn forget(self) {
80 let mut me = std::mem::ManuallyDrop::new(self);
81 me.registry = Weak::new();
82 }
83}
84
85impl<E: Send + Sync + 'static> Drop for AsyncHandlerGuard<E> {
86 fn drop(&mut self) {
87 if let Some(registry) = self.registry.upgrade() {
88 let _ = registry.unregister(self.id);
89 }
90 }
91}
92
93impl<E: Send + Sync + 'static> core::fmt::Debug for AsyncHandlerGuard<E> {
94 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
95 f.debug_struct("AsyncHandlerGuard")
96 .field("id", &self.id)
97 .field("registry_alive", &(self.registry.strong_count() > 0))
98 .finish()
99 }
100}