reactive_signals/runtimes/
client.rs

1use crate::CellType;
2
3use super::{Runtime, RuntimeInner, Scope};
4
5thread_local! {
6  pub static RUNTIME: SingleClientRuntime = Default::default();
7}
8
9#[derive(Default)]
10pub struct SingleClientRuntime(CellType<RuntimeInner<ClientRuntime>>);
11
12/// A runtime meant to be used client-side because there can only be one per thread.
13/// 
14/// 
15/// ```no_run
16/// use reactive_signals::{Scope, signal, runtimes::ClientRuntime};
17/// 
18/// // when starting a client you create the root scope
19/// let sc = ClientRuntime::new_root_scope();
20/// 
21/// // this scope is then used for building a tree of scopes.
22/// app(sc);
23/// 
24/// // calling discard() on the root scope will discard the ClientRuntime as well.
25/// sc.discard();
26/// 
27/// fn app(sc: Scope<ClientRuntime>) {
28///     // a signal marked with `server` will not run in a Scope<ClientRuntime>
29///     let sig = signal!(sc, server, move || println!("server!"));
30/// }
31/// ```
32/// 
33/// See [runtimes](super) for full documentation.
34/// 
35#[derive(Default, Clone, Copy)]
36pub struct ClientRuntime;
37
38impl Runtime for ClientRuntime {
39    const IS_SERVER: bool = false;
40    
41    fn with_mut<F, T>(&self, f: F) -> T
42    where
43        F: FnOnce(&mut RuntimeInner<ClientRuntime>) -> T,
44    {
45        RUNTIME.with(|rt| f(&mut rt.rt_mut()))
46    }
47
48    fn with_ref<F, T>(&self, f: F) -> T
49    where
50        F: FnOnce(&RuntimeInner<ClientRuntime>) -> T,
51    {
52        RUNTIME.with(|rt| f(&rt.rt_ref()))
53    }
54
55}
56
57impl  ClientRuntime {
58    pub fn new_root_scope() -> Scope<ClientRuntime> {
59        RUNTIME.with(|rt| {
60            #[allow(unused_mut)]
61            let mut data = rt.rt_mut();
62            if data.in_use() {
63                panic!("Runtime is already used. Make sure to not call new_root_scope() more than once on a thread");
64            }
65            let mut rti = RuntimeInner::new();
66            let sx = rti.scope_tree.init(Default::default());
67            *data = rti;
68
69            Scope {
70                sx,
71                rt: ClientRuntime,
72            }
73    
74        })
75    }
76
77    #[cfg(any(test, feature = "profile"))]
78    pub fn bench_root_scope() -> Scope<ClientRuntime> {
79        RUNTIME.with(|rt| {
80            drop(rt.rt_mut().discard());
81            Self::new_root_scope()
82        })
83    }
84}
85
86#[cfg(not(feature = "unsafe-cell"))]
87impl SingleClientRuntime {
88    #[inline]
89    fn rt_ref(&self) -> std::cell::Ref<RuntimeInner<ClientRuntime>> {
90        self.0.borrow()
91    }
92
93    #[inline]
94    fn rt_mut(&self) -> std::cell::RefMut<RuntimeInner<ClientRuntime>> {
95        self.0.borrow_mut()
96    }
97
98}
99#[cfg(feature = "unsafe-cell")]
100impl SingleClientRuntime {
101    #[inline]
102    fn rt_ref(&self) -> &RuntimeInner<ClientRuntime> {
103        unsafe { &*self.0.get() }
104    }
105
106    #[inline]
107    fn rt_mut(&self) -> &mut RuntimeInner<ClientRuntime> {
108        unsafe { &mut *self.0.get() }
109    }
110}