Skip to main content

reactive_graph/signal/
trigger.rs

1use super::{subscriber_traits::AsSubscriberSet, ArcTrigger};
2use crate::{
3    graph::{ReactiveNode, SubscriberSet},
4    owner::ArenaItem,
5    traits::{DefinedAt, Dispose, IsDisposed, Notify},
6};
7use std::{
8    fmt::{Debug, Formatter, Result},
9    panic::Location,
10    sync::{Arc, RwLock},
11};
12
13/// A trigger is a data-less signal with the sole purpose of notifying other reactive code of a change.
14///
15/// This can be useful for when using external data not stored in signals, for example.
16///
17/// This is an arena-allocated Trigger, which is `Copy` and is disposed when its reactive
18/// [`Owner`](crate::owner::Owner) cleans up. For a reference-counted trigger that lives
19/// as long as a reference to it is alive, see [`ArcTrigger`].
20pub struct Trigger {
21    #[cfg(any(debug_assertions, leptos_debuginfo))]
22    pub(crate) defined_at: &'static Location<'static>,
23    pub(crate) inner: ArenaItem<ArcTrigger>,
24}
25
26impl Trigger {
27    /// Creates a new trigger.
28    #[track_caller]
29    pub fn new() -> Self {
30        Self {
31            #[cfg(any(debug_assertions, leptos_debuginfo))]
32            defined_at: Location::caller(),
33            inner: ArenaItem::new(ArcTrigger::new()),
34        }
35    }
36}
37
38impl Default for Trigger {
39    fn default() -> Self {
40        Self::new()
41    }
42}
43
44impl Clone for Trigger {
45    #[track_caller]
46    fn clone(&self) -> Self {
47        *self
48    }
49}
50
51impl Copy for Trigger {}
52
53impl Debug for Trigger {
54    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
55        f.debug_struct("Trigger").finish()
56    }
57}
58
59impl Dispose for Trigger {
60    fn dispose(self) {
61        self.inner.dispose()
62    }
63}
64
65impl IsDisposed for Trigger {
66    #[inline(always)]
67    fn is_disposed(&self) -> bool {
68        self.inner.is_disposed()
69    }
70}
71
72impl AsSubscriberSet for Trigger {
73    type Output = Arc<RwLock<SubscriberSet>>;
74
75    #[inline(always)]
76    fn as_subscriber_set(&self) -> Option<Self::Output> {
77        self.inner
78            .try_get_value()
79            .and_then(|arc_trigger| arc_trigger.as_subscriber_set())
80    }
81}
82
83impl DefinedAt for Trigger {
84    #[inline(always)]
85    fn defined_at(&self) -> Option<&'static Location<'static>> {
86        #[cfg(any(debug_assertions, leptos_debuginfo))]
87        {
88            Some(self.defined_at)
89        }
90        #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
91        {
92            None
93        }
94    }
95}
96
97impl Notify for Trigger {
98    fn notify(&self) {
99        if let Some(inner) = self.inner.try_get_value() {
100            inner.mark_dirty();
101        }
102    }
103}