freya_core/
current_context.rs

1use std::{
2    cell::RefCell,
3    rc::Rc,
4    sync::atomic::AtomicU64,
5};
6
7use rustc_hash::FxHashMap;
8
9use crate::{
10    prelude::{
11        Task,
12        TaskId,
13    },
14    reactive_context::ReactiveContext,
15    runner::Message,
16    scope::ScopeStorage,
17    scope_id::ScopeId,
18};
19
20// TODO: rendering flag.
21pub struct CurrentContext {
22    pub scope_id: ScopeId,
23    pub scopes_storages: Rc<RefCell<FxHashMap<ScopeId, ScopeStorage>>>,
24
25    pub tasks: Rc<RefCell<FxHashMap<TaskId, Rc<RefCell<Task>>>>>,
26    pub task_id_counter: Rc<AtomicU64>,
27    pub sender: futures_channel::mpsc::UnboundedSender<Message>,
28}
29
30impl CurrentContext {
31    pub fn run_with_reactive<T>(new_context: Self, run: impl FnOnce() -> T) -> T {
32        let reactive_context = CURRENT_CONTEXT.with_borrow_mut(|context| {
33            let reactive_context = {
34                let scope_storages = new_context.scopes_storages.borrow();
35                let scope_storage = scope_storages.get(&new_context.scope_id).unwrap();
36                scope_storage.reactive_context.clone()
37            };
38            context.replace(new_context);
39            reactive_context
40        });
41        let res = ReactiveContext::run(reactive_context, run);
42        CURRENT_CONTEXT.with_borrow_mut(|context| context.take());
43        res
44    }
45
46    pub fn run<T>(new_context: Self, run: impl FnOnce() -> T) -> T {
47        CURRENT_CONTEXT.with_borrow_mut(|context| {
48            context.replace(new_context);
49        });
50        let res = run();
51        CURRENT_CONTEXT.with_borrow_mut(|context| context.take());
52        res
53    }
54
55    pub fn with<T>(with: impl FnOnce(&CurrentContext) -> T) -> T {
56        CURRENT_CONTEXT.with(|context| with(context.borrow().as_ref().expect("Your trying to access Freya's current context outside of it, you might be in a separate thread or async task that is not integrated with Freya.")))
57    }
58}
59
60thread_local! {
61    static CURRENT_CONTEXT: RefCell<Option<CurrentContext>> = const { RefCell::new(None) }
62}