Skip to main content

rustolio_web/hooks/effect/
mod.rs

1//
2// SPDX-License-Identifier: MPL-2.0
3//
4// Copyright (c) 2026 Tobias Binnewies. All rights reserved.
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at http://mozilla.org/MPL/2.0/.
9//
10
11mod store;
12
13use std::usize;
14
15use super::{Scope, signal_updater_callback};
16
17pub(super) use store::EffectStore;
18
19/// Runs always on creation and on every updated of the readed signals
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub struct Effect {
22    id: usize,
23}
24
25impl Effect {
26    pub fn new(f: impl Fn() + 'static) -> Self {
27        let id = EffectStore::new();
28        Scope::register_effect(id);
29
30        signal_updater_callback(move || !EffectStore::is_dropped(id), f);
31
32        Self { id }
33    }
34
35    pub fn new_result(f: impl Fn() -> rustolio_utils::Result<()> + 'static) -> Self {
36        Self::new(crate::error::convert_fn_0("Effect", f))
37    }
38
39    pub fn remove(&self) {
40        #[cfg(debug_assertions)]
41        if self.id == usize::MAX {
42            panic!("Cannot drop global effect")
43        }
44
45        EffectStore::drop(self.id);
46    }
47
48    /// Should only called using the [`global!`] macro.
49    ///
50    /// # Unsafe
51    /// Breaks if scoped signals are used inside the closure OR if this is not called directly after the effects creation.
52    ///
53    /// [`global!`]: crate::prelude::global!
54    #[doc(hidden)]
55    pub unsafe fn deregister(&mut self) {
56        unsafe {
57            // SAFETY: Caller is responsible for safe call.
58            Scope::deregister_effect(self.id)
59        };
60        self.id = usize::MAX;
61    }
62}