Skip to main content

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}