Skip to main content

tokens/
token.rs

1use std::{any::Any, ops::Deref, sync::Arc};
2
3/// Represents the state associated with a change notification.
4pub type State = Option<Arc<dyn Any + Send + Sync>>;
5
6/// Represents a change notification callback.
7pub type Callback = Box<dyn Fn(State) + Send + Sync>;
8
9type CallbackRef = Arc<dyn Fn(State) + Send + Sync>;
10
11/// Represents a [`ChangeToken`](crate::ChangeToken) registration.
12///
13/// # Remarks
14///
15/// When the registration is dropped, the underlying callback is unregistered.
16pub struct Registration(#[allow(dead_code)] CallbackRef);
17
18impl Registration {
19    /// Initializes a new change token registration.
20    #[inline]
21    pub fn new(callback: CallbackRef) -> Self {
22        Self(callback)
23    }
24
25    /// Initializes a new, empty change token registration.
26    #[inline]
27    pub fn none() -> Self {
28        Self::default()
29    }
30}
31
32impl Default for Registration {
33    #[inline]
34    fn default() -> Self {
35        Self(Arc::new(|_| {}))
36    }
37}
38
39/// Propagates notifications that a change has occurred.
40pub trait ChangeToken: Send + Sync {
41    /// Gets a value that indicates if a change has occurred.
42    fn changed(&self) -> bool;
43
44    /// Indicates if this token will proactively raise callbacks.
45    ///
46    /// # Remarks
47    ///
48    /// If `false`, the token consumer should expect for that any callback
49    /// specified in [`register`](ChangeToken::register) will be invoked
50    /// when a change occurs. If `false`, the token consumer must poll
51    /// [`changed`](ChangeToken::changed) to detect changes.
52    fn must_poll(&self) -> bool {
53        false
54    }
55
56    /// Registers for a callback that will be invoked when the token has changed.
57    ///
58    /// # Arguments
59    ///
60    /// * `callback` - The callback to invoke
61    /// * `state` - The optional [state](State) provided to the callback, if any
62    ///
63    /// # Returns
64    ///
65    /// An opaque change token [registration](Registration). When it
66    /// is dropped, the callback function is unregistered.
67    #[must_use]
68    fn register(&self, callback: Callback, state: State) -> Registration;
69}
70
71// this allows Box<dyn ChangeToken> to be used for T: ChangeToken
72impl ChangeToken for Box<dyn ChangeToken> {
73    #[inline]
74    fn changed(&self) -> bool {
75        self.deref().changed()
76    }
77
78    #[inline]
79    fn must_poll(&self) -> bool {
80        self.deref().must_poll()
81    }
82
83    #[inline]
84    fn register(&self, callback: Callback, state: State) -> Registration {
85        self.deref().register(callback, state)
86    }
87}