mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-11 21:13:02 +00:00
Checkpoint
This commit is contained in:
parent
b6a3d9ce59
commit
a9c69bf774
5 changed files with 150 additions and 55 deletions
|
@ -9,15 +9,15 @@ use refineable::Refineable;
|
|||
|
||||
use crate::{
|
||||
current_platform, image_cache::ImageCache, AssetSource, Context, DisplayId, Executor, LayoutId,
|
||||
MainThread, MainThreadOnly, Platform, PlatformDisplayLinker, RootView, SvgRenderer, Task,
|
||||
TextStyle, TextStyleRefinement, TextSystem, Window, WindowContext, WindowHandle, WindowId,
|
||||
MainThread, MainThreadOnly, Platform, PlatformDisplayLinker, RootView, SubscriberSet,
|
||||
SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem, Window, WindowContext,
|
||||
WindowHandle, WindowId,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use collections::{HashMap, VecDeque};
|
||||
use futures::Future;
|
||||
use parking_lot::Mutex;
|
||||
use slotmap::SlotMap;
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
any::{type_name, Any, TypeId},
|
||||
mem,
|
||||
|
@ -67,8 +67,8 @@ impl App {
|
|||
entities,
|
||||
windows: SlotMap::with_key(),
|
||||
pending_effects: Default::default(),
|
||||
observers: Default::default(),
|
||||
event_handlers: Default::default(),
|
||||
observers: SubscriberSet::new(),
|
||||
event_handlers: SubscriberSet::new(),
|
||||
layout_id_buffer: Default::default(),
|
||||
})
|
||||
}))
|
||||
|
@ -88,9 +88,8 @@ impl App {
|
|||
}
|
||||
}
|
||||
|
||||
type Handlers = SmallVec<[Arc<dyn Fn(&mut AppContext) -> bool + Send + Sync + 'static>; 2]>;
|
||||
type EventHandlers =
|
||||
SmallVec<[Arc<dyn Fn(&dyn Any, &mut AppContext) -> bool + Send + Sync + 'static>; 2]>;
|
||||
type Handler = Arc<dyn Fn(&mut AppContext) -> bool + Send + Sync + 'static>;
|
||||
type EventHandler = Arc<dyn Fn(&dyn Any, &mut AppContext) -> bool + Send + Sync + 'static>;
|
||||
type FrameCallback = Box<dyn FnOnce(&mut WindowContext) + Send>;
|
||||
|
||||
pub struct AppContext {
|
||||
|
@ -109,8 +108,8 @@ pub struct AppContext {
|
|||
pub(crate) entities: EntityMap,
|
||||
pub(crate) windows: SlotMap<WindowId, Option<Window>>,
|
||||
pub(crate) pending_effects: VecDeque<Effect>,
|
||||
pub(crate) observers: HashMap<EntityId, Handlers>,
|
||||
pub(crate) event_handlers: HashMap<EntityId, EventHandlers>,
|
||||
pub(crate) observers: SubscriberSet<EntityId, Handler>,
|
||||
pub(crate) event_handlers: SubscriberSet<EntityId, EventHandler>,
|
||||
pub(crate) layout_id_buffer: Vec<LayoutId>, // We recycle this memory across layout requests.
|
||||
}
|
||||
|
||||
|
@ -176,23 +175,15 @@ impl AppContext {
|
|||
}
|
||||
|
||||
fn apply_notify_effect(&mut self, updated_entity: EntityId) {
|
||||
if let Some(mut handlers) = self.observers.remove(&updated_entity) {
|
||||
handlers.retain(|handler| handler(self));
|
||||
if let Some(new_handlers) = self.observers.remove(&updated_entity) {
|
||||
handlers.extend(new_handlers);
|
||||
}
|
||||
self.observers.insert(updated_entity, handlers);
|
||||
}
|
||||
self.observers
|
||||
.clone()
|
||||
.retain(&updated_entity, |handler| handler(self));
|
||||
}
|
||||
|
||||
fn apply_emit_effect(&mut self, updated_entity: EntityId, event: Box<dyn Any>) {
|
||||
if let Some(mut handlers) = self.event_handlers.remove(&updated_entity) {
|
||||
handlers.retain(|handler| handler(&event, self));
|
||||
if let Some(new_handlers) = self.event_handlers.remove(&updated_entity) {
|
||||
handlers.extend(new_handlers);
|
||||
}
|
||||
self.event_handlers.insert(updated_entity, handlers);
|
||||
}
|
||||
self.event_handlers
|
||||
.clone()
|
||||
.retain(&updated_entity, |handler| handler(&event, self));
|
||||
}
|
||||
|
||||
pub fn to_async(&self) -> AsyncAppContext {
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use crate::{AppContext, Context, Effect, EntityId, EventEmitter, Handle, Reference, WeakHandle};
|
||||
use crate::{
|
||||
AppContext, Context, Effect, EntityId, EventEmitter, Handle, Reference, Subscription,
|
||||
WeakHandle,
|
||||
};
|
||||
use std::{marker::PhantomData, sync::Arc};
|
||||
|
||||
pub struct ModelContext<'a, T> {
|
||||
|
@ -42,21 +45,20 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
|||
&mut self,
|
||||
handle: &Handle<E>,
|
||||
on_notify: impl Fn(&mut T, Handle<E>, &mut ModelContext<'_, T>) + Send + Sync + 'static,
|
||||
) {
|
||||
) -> Subscription {
|
||||
let this = self.handle();
|
||||
let handle = handle.downgrade();
|
||||
self.app
|
||||
.observers
|
||||
.entry(handle.id)
|
||||
.or_default()
|
||||
.push(Arc::new(move |cx| {
|
||||
self.app.observers.insert(
|
||||
handle.id,
|
||||
Arc::new(move |cx| {
|
||||
if let Some((this, handle)) = this.upgrade(cx).zip(handle.upgrade(cx)) {
|
||||
this.update(cx, |this, cx| on_notify(this, handle, cx));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}));
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn subscribe<E: EventEmitter + Send + Sync + 'static>(
|
||||
|
@ -66,14 +68,12 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
|||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
) {
|
||||
) -> Subscription {
|
||||
let this = self.handle();
|
||||
let handle = handle.downgrade();
|
||||
self.app
|
||||
.event_handlers
|
||||
.entry(handle.id)
|
||||
.or_default()
|
||||
.push(Arc::new(move |event, cx| {
|
||||
self.app.event_handlers.insert(
|
||||
handle.id,
|
||||
Arc::new(move |event, cx| {
|
||||
let event = event.downcast_ref().expect("invalid event type");
|
||||
if let Some((this, handle)) = this.upgrade(cx).zip(handle.upgrade(cx)) {
|
||||
this.update(cx, |this, cx| on_event(this, handle, event, cx));
|
||||
|
@ -81,7 +81,8 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
|||
} else {
|
||||
false
|
||||
}
|
||||
}));
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn notify(&mut self) {
|
||||
|
|
|
@ -13,6 +13,7 @@ mod scene;
|
|||
mod style;
|
||||
mod style_helpers;
|
||||
mod styled;
|
||||
mod subscription;
|
||||
mod svg_renderer;
|
||||
mod taffy;
|
||||
mod text_system;
|
||||
|
@ -42,6 +43,7 @@ pub use smol::Timer;
|
|||
pub use style::*;
|
||||
pub use style_helpers::*;
|
||||
pub use styled::*;
|
||||
pub use subscription::*;
|
||||
pub use svg_renderer::*;
|
||||
pub use taffy::{AvailableSpace, LayoutId};
|
||||
pub use text_system::*;
|
||||
|
|
103
crates/gpui3/src/subscription.rs
Normal file
103
crates/gpui3/src/subscription.rs
Normal file
|
@ -0,0 +1,103 @@
|
|||
use collections::{BTreeMap, BTreeSet};
|
||||
use parking_lot::Mutex;
|
||||
use std::{fmt::Debug, mem, sync::Arc};
|
||||
use util::post_inc;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct SubscriberSet<EmitterKey, Callback>(
|
||||
Arc<Mutex<SubscriberSetState<EmitterKey, Callback>>>,
|
||||
);
|
||||
|
||||
struct SubscriberSetState<EmitterKey, Callback> {
|
||||
subscribers: BTreeMap<EmitterKey, BTreeMap<usize, Callback>>,
|
||||
dropped_subscribers: BTreeSet<(EmitterKey, usize)>,
|
||||
next_subscriber_id: usize,
|
||||
}
|
||||
|
||||
impl<EmitterKey, Callback> SubscriberSet<EmitterKey, Callback>
|
||||
where
|
||||
EmitterKey: 'static + Ord + Clone + Debug,
|
||||
Callback: 'static,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
Self(Arc::new(Mutex::new(SubscriberSetState {
|
||||
subscribers: Default::default(),
|
||||
dropped_subscribers: Default::default(),
|
||||
next_subscriber_id: 0,
|
||||
})))
|
||||
}
|
||||
|
||||
pub fn insert(&self, emitter: EmitterKey, callback: Callback) -> Subscription {
|
||||
let mut lock = self.0.lock();
|
||||
let subscriber_id = post_inc(&mut lock.next_subscriber_id);
|
||||
lock.subscribers
|
||||
.entry(emitter.clone())
|
||||
.or_default()
|
||||
.insert(subscriber_id, callback);
|
||||
let this = self.0.clone();
|
||||
Subscription {
|
||||
unsubscribe: Some(Box::new(move || {
|
||||
let mut lock = this.lock();
|
||||
if let Some(subscribers) = lock.subscribers.get_mut(&emitter) {
|
||||
subscribers.remove(&subscriber_id);
|
||||
if subscribers.is_empty() {
|
||||
lock.subscribers.remove(&emitter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't manage to remove the subscription, which means it was dropped
|
||||
// while invoking the callback. Mark it as dropped so that we can remove it
|
||||
// later.
|
||||
lock.dropped_subscribers.insert((emitter, subscriber_id));
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn retain<F>(&self, emitter: &EmitterKey, mut f: F)
|
||||
where
|
||||
F: FnMut(&mut Callback) -> bool,
|
||||
{
|
||||
let entry = self.0.lock().subscribers.remove_entry(emitter);
|
||||
if let Some((emitter, mut subscribers)) = entry {
|
||||
subscribers.retain(|_, callback| f(callback));
|
||||
let mut lock = self.0.lock();
|
||||
|
||||
// Add any new subscribers that were added while invoking the callback.
|
||||
if let Some(new_subscribers) = lock.subscribers.remove(&emitter) {
|
||||
subscribers.extend(new_subscribers);
|
||||
}
|
||||
|
||||
// Remove any dropped subscriptions that were dropped while invoking the callback.
|
||||
for (dropped_emitter, dropped_subscription_id) in
|
||||
mem::take(&mut lock.dropped_subscribers)
|
||||
{
|
||||
debug_assert_eq!(emitter, dropped_emitter);
|
||||
subscribers.remove(&dropped_subscription_id);
|
||||
}
|
||||
|
||||
if !subscribers.is_empty() {
|
||||
lock.subscribers.insert(emitter, subscribers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub struct Subscription {
|
||||
unsubscribe: Option<Box<dyn FnOnce()>>,
|
||||
}
|
||||
|
||||
impl Subscription {
|
||||
pub fn detach(mut self) {
|
||||
self.unsubscribe.take();
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Subscription {
|
||||
fn drop(&mut self) {
|
||||
if let Some(unsubscribe) = self.unsubscribe.take() {
|
||||
unsubscribe();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,8 +5,8 @@ use crate::{
|
|||
LayoutId, MainThread, MainThreadOnly, MonochromeSprite, MouseMoveEvent, Path, Pixels,
|
||||
PlatformAtlas, PlatformWindow, Point, PolychromeSprite, Quad, Reference, RenderGlyphParams,
|
||||
RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size,
|
||||
Style, TaffyLayoutEngine, Task, Underline, UnderlineStyle, WeakHandle, WindowOptions,
|
||||
SUBPIXEL_VARIANTS,
|
||||
Style, Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, WeakHandle,
|
||||
WindowOptions, SUBPIXEL_VARIANTS,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use collections::HashMap;
|
||||
|
@ -903,15 +903,13 @@ impl<'a, 'w, S: Send + Sync + 'static> ViewContext<'a, 'w, S> {
|
|||
&mut self,
|
||||
handle: &Handle<E>,
|
||||
on_notify: impl Fn(&mut S, Handle<E>, &mut ViewContext<'_, '_, S>) + Send + Sync + 'static,
|
||||
) {
|
||||
) -> Subscription {
|
||||
let this = self.handle();
|
||||
let handle = handle.downgrade();
|
||||
let window_handle = self.window.handle;
|
||||
self.app
|
||||
.observers
|
||||
.entry(handle.id)
|
||||
.or_default()
|
||||
.push(Arc::new(move |cx| {
|
||||
self.app.observers.insert(
|
||||
handle.id,
|
||||
Arc::new(move |cx| {
|
||||
cx.update_window(window_handle.id, |cx| {
|
||||
if let Some(handle) = handle.upgrade(cx) {
|
||||
this.update(cx, |this, cx| on_notify(this, handle, cx))
|
||||
|
@ -921,7 +919,8 @@ impl<'a, 'w, S: Send + Sync + 'static> ViewContext<'a, 'w, S> {
|
|||
}
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}));
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn subscribe<E: EventEmitter + Send + Sync + 'static>(
|
||||
|
@ -931,15 +930,13 @@ impl<'a, 'w, S: Send + Sync + 'static> ViewContext<'a, 'w, S> {
|
|||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
) {
|
||||
) -> Subscription {
|
||||
let this = self.handle();
|
||||
let handle = handle.downgrade();
|
||||
let window_handle = self.window.handle;
|
||||
self.app
|
||||
.event_handlers
|
||||
.entry(handle.id)
|
||||
.or_default()
|
||||
.push(Arc::new(move |event, cx| {
|
||||
self.app.event_handlers.insert(
|
||||
handle.id,
|
||||
Arc::new(move |event, cx| {
|
||||
cx.update_window(window_handle.id, |cx| {
|
||||
if let Some(handle) = handle.upgrade(cx) {
|
||||
let event = event.downcast_ref().expect("invalid event type");
|
||||
|
@ -950,7 +947,8 @@ impl<'a, 'w, S: Send + Sync + 'static> ViewContext<'a, 'w, S> {
|
|||
}
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}));
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn notify(&mut self) {
|
||||
|
|
Loading…
Reference in a new issue