Outline a bunch of methods in gpui that leaked SubscriberSet types (#7430)

This takes down LLVM IR size of theme_selector from 316k to ~250k. Note
that I do not care about theme_selector in particular, though it acts as
a benchmark for smaller crates to me ("how much static overhead in
compile time does gpui have").

The title is a bit dramatic, so just to shed some light: by leaking a
type I mean forcing downstream crates to codegen it's methods/know about
it's drop code. Since SubscriberSet is no longer used directly in the
generic (==inlineable) methods, users no longer have to codegen `insert`
and co.

Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2024-02-06 11:10:15 +01:00 committed by GitHub
parent c591681bad
commit 1446fb7632
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 70 additions and 53 deletions

View file

@ -380,6 +380,11 @@ impl AppContext {
})
}
pub(crate) fn new_observer(&mut self, key: EntityId, value: Handler) -> Subscription {
let (subscription, activate) = self.observers.insert(key, value);
self.defer(move |_| activate());
subscription
}
pub(crate) fn observe_internal<W, E>(
&mut self,
entity: &E,
@ -391,7 +396,7 @@ impl AppContext {
{
let entity_id = entity.entity_id();
let handle = entity.downgrade();
let (subscription, activate) = self.observers.insert(
self.new_observer(
entity_id,
Box::new(move |cx| {
if let Some(handle) = E::upgrade_from(&handle) {
@ -400,9 +405,7 @@ impl AppContext {
false
}
}),
);
self.defer(move |_| activate());
subscription
)
}
/// Arrange for the given callback to be invoked whenever the given model or view emits an event of a given type.
@ -423,6 +426,15 @@ impl AppContext {
})
}
pub(crate) fn new_subscription(
&mut self,
key: EntityId,
value: (TypeId, Listener),
) -> Subscription {
let (subscription, activate) = self.event_listeners.insert(key, value);
self.defer(move |_| activate());
subscription
}
pub(crate) fn subscribe_internal<T, E, Evt>(
&mut self,
entity: &E,
@ -435,7 +447,7 @@ impl AppContext {
{
let entity_id = entity.entity_id();
let entity = entity.downgrade();
let (subscription, activate) = self.event_listeners.insert(
self.new_subscription(
entity_id,
(
TypeId::of::<Evt>(),
@ -448,9 +460,7 @@ impl AppContext {
}
}),
),
);
self.defer(move |_| activate());
subscription
)
}
/// Returns handles to all open windows in the application.
@ -930,13 +940,22 @@ impl AppContext {
self.globals_by_type.insert(global_type, lease.global);
}
pub(crate) fn new_view_observer(
&mut self,
key: TypeId,
value: NewViewListener,
) -> Subscription {
let (subscription, activate) = self.new_view_observers.insert(key, value);
activate();
subscription
}
/// Arrange for the given function to be invoked whenever a view of the specified type is created.
/// The function will be passed a mutable reference to the view along with an appropriate context.
pub fn observe_new_views<V: 'static>(
&mut self,
on_new: impl 'static + Fn(&mut V, &mut ViewContext<V>),
) -> Subscription {
let (subscription, activate) = self.new_view_observers.insert(
self.new_view_observer(
TypeId::of::<V>(),
Box::new(move |any_view: AnyView, cx: &mut WindowContext| {
any_view
@ -946,9 +965,7 @@ impl AppContext {
on_new(view_state, cx);
})
}),
);
activate();
subscription
)
}
/// Observe the release of a model or view. The callback is invoked after the model or view
@ -980,9 +997,15 @@ impl AppContext {
&mut self,
f: impl FnMut(&KeystrokeEvent, &mut WindowContext) + 'static,
) -> Subscription {
let (subscription, activate) = self.keystroke_observers.insert((), Box::new(f));
activate();
subscription
fn inner(
keystroke_observers: &mut SubscriberSet<(), KeystrokeObserver>,
handler: KeystrokeObserver,
) -> Subscription {
let (subscription, activate) = keystroke_observers.insert((), handler);
activate();
subscription
}
inner(&mut self.keystroke_observers, Box::new(f))
}
pub(crate) fn push_text_style(&mut self, text_style: TextStyleRefinement) {