From 5ec003530f9f3bab540e1150af1b6c29a50329d1 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 29 Nov 2021 14:16:19 -0800 Subject: [PATCH] Consolidate pending effects logic into MutableAppContext::update Co-Authored-By: Nathan Sobo --- crates/gpui/src/app.rs | 344 ++++++++++++++++++----------------------- 1 file changed, 152 insertions(+), 192 deletions(-) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 90dcb5365b..d731167edc 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -342,10 +342,8 @@ impl App { fn update T>(&mut self, callback: F) -> T { let mut state = self.0.borrow_mut(); - state.pending_flushes += 1; - let result = callback(&mut *state); + let result = state.update(callback); state.pending_notifications.clear(); - state.flush_effects(); result } } @@ -406,11 +404,7 @@ impl TestAppContext { T: Entity, F: FnOnce(&mut ModelContext) -> T, { - let mut state = self.cx.borrow_mut(); - state.pending_flushes += 1; - let handle = state.add_model(build_model); - state.flush_effects(); - handle + self.cx.borrow_mut().add_model(build_model) } pub fn add_window(&mut self, build_root_view: F) -> (usize, ViewHandle) @@ -436,11 +430,7 @@ impl TestAppContext { T: View, F: FnOnce(&mut ViewContext) -> T, { - let mut state = self.cx.borrow_mut(); - state.pending_flushes += 1; - let handle = state.add_view(window_id, build_view); - state.flush_effects(); - handle + self.cx.borrow_mut().add_view(window_id, build_view) } pub fn add_option_view( @@ -452,11 +442,7 @@ impl TestAppContext { T: View, F: FnOnce(&mut ViewContext) -> Option, { - let mut state = self.cx.borrow_mut(); - state.pending_flushes += 1; - let handle = state.add_option_view(window_id, build_view); - state.flush_effects(); - handle + self.cx.borrow_mut().add_option_view(window_id, build_view) } pub fn read T>(&self, callback: F) -> T { @@ -535,11 +521,7 @@ impl AsyncAppContext { } pub fn update T>(&mut self, callback: F) -> T { - let mut state = self.0.borrow_mut(); - state.pending_flushes += 1; - let result = callback(&mut *state); - state.flush_effects(); - result + self.0.borrow_mut().update(callback) } pub fn add_model(&mut self, build_model: F) -> ModelHandle @@ -569,11 +551,7 @@ impl UpdateModel for AsyncAppContext { handle: &ModelHandle, update: &mut dyn FnMut(&mut E, &mut ModelContext) -> O, ) -> O { - let mut state = self.0.borrow_mut(); - state.pending_flushes += 1; - let result = state.update_model(handle, update); - state.flush_effects(); - result + self.0.borrow_mut().update_model(handle, update) } } @@ -607,11 +585,7 @@ impl UpdateView for AsyncAppContext { where T: View, { - let mut state = self.0.borrow_mut(); - state.pending_flushes += 1; - let result = state.update_view(handle, update); - state.flush_effects(); - result + self.0.borrow_mut().update_view(handle, update) } } @@ -636,11 +610,7 @@ impl UpdateModel for TestAppContext { handle: &ModelHandle, update: &mut dyn FnMut(&mut T, &mut ModelContext) -> O, ) -> O { - let mut state = self.cx.borrow_mut(); - state.pending_flushes += 1; - let result = state.update_model(handle, update); - state.flush_effects(); - result + self.cx.borrow_mut().update_model(handle, update) } } @@ -665,11 +635,7 @@ impl UpdateView for TestAppContext { where T: View, { - let mut state = self.cx.borrow_mut(); - state.pending_flushes += 1; - let result = state.update_view(handle, update); - state.flush_effects(); - result + self.cx.borrow_mut().update_view(handle, update) } } @@ -727,6 +693,7 @@ impl MutableAppContext { foreground_platform: Rc, font_cache: Arc, asset_source: impl AssetSource, + // entity_drop_tx: ) -> Self { Self { weak_self: None, @@ -941,9 +908,9 @@ impl MutableAppContext { .collect() } - pub fn update T>(&mut self, callback: F) -> T { + pub fn update T>(&mut self, callback: F) -> T { self.pending_flushes += 1; - let result = callback(); + let result = callback(self); self.flush_effects(); result } @@ -1124,46 +1091,44 @@ impl MutableAppContext { path: &[usize], action: &dyn AnyAction, ) -> bool { - self.pending_flushes += 1; - let mut halted_dispatch = false; + self.update(|this| { + let mut halted_dispatch = false; + for view_id in path.iter().rev() { + if let Some(mut view) = this.cx.views.remove(&(window_id, *view_id)) { + let type_id = view.as_any().type_id(); - for view_id in path.iter().rev() { - if let Some(mut view) = self.cx.views.remove(&(window_id, *view_id)) { - let type_id = view.as_any().type_id(); - - if let Some((name, mut handlers)) = self - .actions - .get_mut(&type_id) - .and_then(|h| h.remove_entry(&action.id())) - { - for handler in handlers.iter_mut().rev() { - let halt_dispatch = - handler(view.as_mut(), action, self, window_id, *view_id); - if halt_dispatch { - halted_dispatch = true; - break; - } - } - self.actions + if let Some((name, mut handlers)) = this + .actions .get_mut(&type_id) - .unwrap() - .insert(name, handlers); - } + .and_then(|h| h.remove_entry(&action.id())) + { + for handler in handlers.iter_mut().rev() { + let halt_dispatch = + handler(view.as_mut(), action, this, window_id, *view_id); + if halt_dispatch { + halted_dispatch = true; + break; + } + } + this.actions + .get_mut(&type_id) + .unwrap() + .insert(name, handlers); + } - self.cx.views.insert((window_id, *view_id), view); + this.cx.views.insert((window_id, *view_id), view); - if halted_dispatch { - break; + if halted_dispatch { + break; + } } } - } - if !halted_dispatch { - self.dispatch_global_action_any(action); - } - - self.flush_effects(); - halted_dispatch + if !halted_dispatch { + this.dispatch_global_action_any(action); + } + halted_dispatch + }) } pub fn dispatch_global_action(&mut self, action: A) { @@ -1171,14 +1136,14 @@ impl MutableAppContext { } fn dispatch_global_action_any(&mut self, action: &dyn AnyAction) { - if let Some((name, mut handlers)) = self.global_actions.remove_entry(&action.id()) { - self.pending_flushes += 1; - for handler in handlers.iter_mut().rev() { - handler(action, self); + self.update(|this| { + if let Some((name, mut handlers)) = this.global_actions.remove_entry(&action.id()) { + for handler in handlers.iter_mut().rev() { + handler(action, this); + } + this.global_actions.insert(name, handlers); } - self.global_actions.insert(name, handlers); - self.flush_effects(); - } + }) } pub fn add_bindings>(&mut self, bindings: T) { @@ -1230,14 +1195,14 @@ impl MutableAppContext { T: Entity, F: FnOnce(&mut ModelContext) -> T, { - self.pending_flushes += 1; - let model_id = post_inc(&mut self.next_entity_id); - let handle = ModelHandle::new(model_id, &self.cx.ref_counts); - let mut cx = ModelContext::new(self, model_id); - let model = build_model(&mut cx); - self.cx.models.insert(model_id, Box::new(model)); - self.flush_effects(); - handle + self.update(|this| { + let model_id = post_inc(&mut this.next_entity_id); + let handle = ModelHandle::new(model_id, &this.cx.ref_counts); + let mut cx = ModelContext::new(this, model_id); + let model = build_model(&mut cx); + this.cx.models.insert(model_id, Box::new(model)); + handle + }) } pub fn add_window( @@ -1249,26 +1214,26 @@ impl MutableAppContext { T: View, F: FnOnce(&mut ViewContext) -> T, { - self.pending_flushes += 1; - let window_id = post_inc(&mut self.next_window_id); - let root_view = self.add_view(window_id, build_root_view); + self.update(|this| { + let window_id = post_inc(&mut this.next_window_id); + let root_view = this.add_view(window_id, build_root_view); - self.cx.windows.insert( - window_id, - Window { - root_view: root_view.clone().into(), - focused_view_id: root_view.id(), - invalidation: None, - }, - ); - self.open_platform_window(window_id, window_options); - root_view.update(self, |view, cx| { - view.on_focus(cx); - cx.notify(); - }); - self.flush_effects(); + this.cx.windows.insert( + window_id, + Window { + root_view: root_view.clone().into(), + focused_view_id: root_view.id(), + invalidation: None, + }, + ); + this.open_platform_window(window_id, window_options); + root_view.update(this, |view, cx| { + view.on_focus(cx); + cx.notify(); + }); - (window_id, root_view) + (window_id, root_view) + }) } pub fn remove_window(&mut self, window_id: usize) { @@ -1377,25 +1342,25 @@ impl MutableAppContext { T: View, F: FnOnce(&mut ViewContext) -> Option, { - let view_id = post_inc(&mut self.next_entity_id); - self.pending_flushes += 1; - let handle = ViewHandle::new(window_id, view_id, &self.cx.ref_counts); - let mut cx = ViewContext::new(self, window_id, view_id); - let handle = if let Some(view) = build_view(&mut cx) { - self.cx.views.insert((window_id, view_id), Box::new(view)); - if let Some(window) = self.cx.windows.get_mut(&window_id) { - window - .invalidation - .get_or_insert_with(Default::default) - .updated - .insert(view_id); - } - Some(handle) - } else { - None - }; - self.flush_effects(); - handle + self.update(|this| { + let view_id = post_inc(&mut this.next_entity_id); + let handle = ViewHandle::new(window_id, view_id, &this.cx.ref_counts); + let mut cx = ViewContext::new(this, window_id, view_id); + let handle = if let Some(view) = build_view(&mut cx) { + this.cx.views.insert((window_id, view_id), Box::new(view)); + if let Some(window) = this.cx.windows.get_mut(&window_id) { + window + .invalidation + .get_or_insert_with(Default::default) + .updated + .insert(view_id); + } + Some(handle) + } else { + None + }; + handle + }) } pub fn element_state( @@ -1647,27 +1612,25 @@ impl MutableAppContext { return; } - self.pending_flushes += 1; + self.update(|this| { + let blurred_id = this.cx.windows.get_mut(&window_id).map(|window| { + let blurred_id = window.focused_view_id; + window.focused_view_id = focused_id; + blurred_id + }); - let blurred_id = self.cx.windows.get_mut(&window_id).map(|window| { - let blurred_id = window.focused_view_id; - window.focused_view_id = focused_id; - blurred_id - }); - - if let Some(blurred_id) = blurred_id { - if let Some(mut blurred_view) = self.cx.views.remove(&(window_id, blurred_id)) { - blurred_view.on_blur(self, window_id, blurred_id); - self.cx.views.insert((window_id, blurred_id), blurred_view); + if let Some(blurred_id) = blurred_id { + if let Some(mut blurred_view) = this.cx.views.remove(&(window_id, blurred_id)) { + blurred_view.on_blur(this, window_id, blurred_id); + this.cx.views.insert((window_id, blurred_id), blurred_view); + } } - } - if let Some(mut focused_view) = self.cx.views.remove(&(window_id, focused_id)) { - focused_view.on_focus(self, window_id, focused_id); - self.cx.views.insert((window_id, focused_id), focused_view); - } - - self.flush_effects(); + if let Some(mut focused_view) = this.cx.views.remove(&(window_id, focused_id)) { + focused_view.on_focus(this, window_id, focused_id); + this.cx.views.insert((window_id, focused_id), focused_view); + } + }) } pub fn spawn(&self, f: F) -> Task @@ -1713,18 +1676,18 @@ impl UpdateModel for MutableAppContext { update: &mut dyn FnMut(&mut T, &mut ModelContext) -> V, ) -> V { if let Some(mut model) = self.cx.models.remove(&handle.model_id) { - self.pending_flushes += 1; - let mut cx = ModelContext::new(self, handle.model_id); - let result = update( - model - .as_any_mut() - .downcast_mut() - .expect("downcast is type safe"), - &mut cx, - ); - self.cx.models.insert(handle.model_id, model); - self.flush_effects(); - result + self.update(|this| { + let mut cx = ModelContext::new(this, handle.model_id); + let result = update( + model + .as_any_mut() + .downcast_mut() + .expect("downcast is type safe"), + &mut cx, + ); + this.cx.models.insert(handle.model_id, model); + result + }) } else { panic!("circular model update"); } @@ -1759,25 +1722,25 @@ impl UpdateView for MutableAppContext { where T: View, { - self.pending_flushes += 1; - let mut view = self - .cx - .views - .remove(&(handle.window_id, handle.view_id)) - .expect("circular view update"); + self.update(|this| { + let mut view = this + .cx + .views + .remove(&(handle.window_id, handle.view_id)) + .expect("circular view update"); - let mut cx = ViewContext::new(self, handle.window_id, handle.view_id); - let result = update( - view.as_any_mut() - .downcast_mut() - .expect("downcast is type safe"), - &mut cx, - ); - self.cx - .views - .insert((handle.window_id, handle.view_id), view); - self.flush_effects(); - result + let mut cx = ViewContext::new(this, handle.window_id, handle.view_id); + let result = update( + view.as_any_mut() + .downcast_mut() + .expect("downcast is type safe"), + &mut cx, + ); + this.cx + .views + .insert((handle.window_id, handle.view_id), view); + result + }) } } @@ -3336,7 +3299,9 @@ struct RefCounts { impl RefCounts { fn inc_model(&mut self, model_id: usize) { match self.entity_counts.entry(model_id) { - Entry::Occupied(mut entry) => *entry.get_mut() += 1, + Entry::Occupied(mut entry) => { + *entry.get_mut() += 1; + } Entry::Vacant(entry) => { entry.insert(1); self.dropped_models.remove(&model_id); @@ -3403,16 +3368,11 @@ impl RefCounts { HashSet<(usize, usize)>, HashSet<(TypeId, ElementStateId)>, ) { - let mut dropped_models = HashSet::new(); - let mut dropped_views = HashSet::new(); - let mut dropped_element_states = HashSet::new(); - std::mem::swap(&mut self.dropped_models, &mut dropped_models); - std::mem::swap(&mut self.dropped_views, &mut dropped_views); - std::mem::swap( - &mut self.dropped_element_states, - &mut dropped_element_states, - ); - (dropped_models, dropped_views, dropped_element_states) + ( + std::mem::take(&mut self.dropped_models), + std::mem::take(&mut self.dropped_views), + std::mem::take(&mut self.dropped_element_states), + ) } } @@ -3719,7 +3679,7 @@ mod tests { assert!(!*model_released.lock()); assert!(!*view_released.lock()); - cx.update(move || { + cx.update(move |_| { drop(model); }); assert!(*model_released.lock()); @@ -3825,7 +3785,7 @@ mod tests { cx.subscribe(&observed_model, |_, _, _, _| {}).detach(); }); - cx.update(|| { + cx.update(|_| { drop(observing_view); drop(observing_model); }); @@ -3917,7 +3877,7 @@ mod tests { cx.observe(&observed_model, |_, _, _| {}).detach(); }); - cx.update(|| { + cx.update(|_| { drop(observing_view); drop(observing_model); });