freya_core/
current_context.rs1use 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
20pub 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}