event_listener_primitives/
handler_id.rs

1use parking_lot::Mutex;
2use std::fmt;
3use std::sync::Arc;
4
5struct Inner {
6    callback: Option<Box<dyn FnOnce() + Send + 'static>>,
7}
8
9impl Drop for Inner {
10    fn drop(&mut self) {
11        if let Some(callback) = self.callback.take() {
12            callback();
13        }
14    }
15}
16
17/// Handler ID keeps event handler in place, once dropped handler will be removed automatically.
18///
19/// [`HandlerId::detach()`] can be used if it is not desirable for handler to be removed
20/// automatically.
21#[must_use = "Handler will be unregistered immediately if not used"]
22#[derive(Clone)]
23pub struct HandlerId {
24    inner: Arc<Mutex<Inner>>,
25}
26
27impl fmt::Debug for HandlerId {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        f.debug_struct("HandlerId").finish()
30    }
31}
32
33impl HandlerId {
34    pub(crate) fn new<F>(f: F) -> HandlerId
35    where
36        F: FnOnce() + Send + 'static,
37    {
38        let inner = Arc::new(Mutex::new(Inner {
39            callback: Some(Box::new(f)),
40        }));
41
42        HandlerId { inner }
43    }
44
45    /// Consumes [`HandlerId`] and prevents handler from being removed automatically.
46    pub fn detach(&self) {
47        // Remove callback such that it is not called in drop implementation
48        self.inner.lock().callback.take();
49    }
50}