async_context.rs

 1use crate::{
 2    AnyWindowHandle, AppContext, Context, Handle, ModelContext, Result, ViewContext, WindowContext,
 3};
 4use anyhow::anyhow;
 5use parking_lot::Mutex;
 6use std::sync::Weak;
 7
 8#[derive(Clone)]
 9pub struct AsyncAppContext(pub(crate) Weak<Mutex<AppContext>>);
10
11impl Context for AsyncAppContext {
12    type EntityContext<'a, 'w, T: 'static + Send + Sync> = ModelContext<'a, T>;
13    type Result<T> = Result<T>;
14
15    fn entity<T: Send + Sync + 'static>(
16        &mut self,
17        build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
18    ) -> Result<Handle<T>> {
19        let app = self
20            .0
21            .upgrade()
22            .ok_or_else(|| anyhow!("app was released"))?;
23        let mut lock = app.lock(); // Does not compile without this variable.
24        Ok(lock.entity(build_entity))
25    }
26
27    fn update_entity<T: Send + Sync + 'static, R>(
28        &mut self,
29        handle: &Handle<T>,
30        update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
31    ) -> Result<R> {
32        let app = self
33            .0
34            .upgrade()
35            .ok_or_else(|| anyhow!("app was released"))?;
36        let mut lock = app.lock(); // Does not compile without this variable.
37        Ok(lock.update_entity(handle, update))
38    }
39}
40
41impl AsyncAppContext {
42    pub fn update_window<R>(
43        &self,
44        handle: AnyWindowHandle,
45        update: impl FnOnce(&mut WindowContext) -> R,
46    ) -> Result<R> {
47        let app = self
48            .0
49            .upgrade()
50            .ok_or_else(|| anyhow!("app was released"))?;
51        let mut app_context = app.lock();
52        app_context.update_window(handle.id, update)
53    }
54}
55
56#[derive(Clone)]
57pub struct AsyncWindowContext {
58    app: AsyncAppContext,
59    window: AnyWindowHandle,
60}
61
62impl AsyncWindowContext {
63    pub fn new(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
64        Self { app, window }
65    }
66}
67
68impl Context for AsyncWindowContext {
69    type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
70    type Result<T> = Result<T>;
71
72    fn entity<R: Send + Sync + 'static>(
73        &mut self,
74        build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, R>) -> R,
75    ) -> Result<Handle<R>> {
76        self.app
77            .update_window(self.window, |cx| cx.entity(build_entity))
78    }
79
80    fn update_entity<T: Send + Sync + 'static, R>(
81        &mut self,
82        handle: &Handle<T>,
83        update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
84    ) -> Result<R> {
85        self.app
86            .update_window(self.window, |cx| cx.update_entity(handle, update))
87    }
88}