Remove GC step for callback collections, always drop callbacks asap
This commit is contained in:
parent
ef192a902a
commit
53cb3a4429
2 changed files with 42 additions and 33 deletions
|
@ -2123,16 +2123,6 @@ impl MutableAppContext {
|
||||||
self.pending_notifications.clear();
|
self.pending_notifications.clear();
|
||||||
self.remove_dropped_entities();
|
self.remove_dropped_entities();
|
||||||
} else {
|
} else {
|
||||||
self.focus_observations.gc();
|
|
||||||
self.global_subscriptions.gc();
|
|
||||||
self.global_observations.gc();
|
|
||||||
self.subscriptions.gc();
|
|
||||||
self.observations.gc();
|
|
||||||
self.window_activation_observations.gc();
|
|
||||||
self.window_fullscreen_observations.gc();
|
|
||||||
self.keystroke_observations.gc();
|
|
||||||
self.release_observations.gc();
|
|
||||||
|
|
||||||
self.remove_dropped_entities();
|
self.remove_dropped_entities();
|
||||||
|
|
||||||
if refreshing {
|
if refreshing {
|
||||||
|
|
|
@ -16,7 +16,17 @@ pub struct Subscription<K: Clone + Hash + Eq, F> {
|
||||||
|
|
||||||
struct Mapping<K, F> {
|
struct Mapping<K, F> {
|
||||||
callbacks: HashMap<K, BTreeMap<usize, F>>,
|
callbacks: HashMap<K, BTreeMap<usize, F>>,
|
||||||
dropped_subscriptions: HashSet<(K, usize)>,
|
dropped_subscriptions: HashMap<K, HashSet<usize>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K: Hash + Eq, F> Mapping<K, F> {
|
||||||
|
fn clear_dropped_state(&mut self, key: &K, subscription_id: usize) -> bool {
|
||||||
|
if let Some(subscriptions) = self.dropped_subscriptions.get_mut(&key) {
|
||||||
|
subscriptions.remove(&subscription_id)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K, F> Default for Mapping<K, F> {
|
impl<K, F> Default for Mapping<K, F> {
|
||||||
|
@ -50,6 +60,14 @@ impl<K: Clone + Hash + Eq + Copy, F> CallbackCollection<K, F> {
|
||||||
self.internal.lock().callbacks.is_empty()
|
self.internal.lock().callbacks.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn count(&self, key: K) -> usize {
|
||||||
|
self.internal
|
||||||
|
.lock()
|
||||||
|
.callbacks
|
||||||
|
.get(&key)
|
||||||
|
.map_or(0, |callbacks| callbacks.len())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn subscribe(&mut self, key: K, subscription_id: usize) -> Subscription<K, F> {
|
pub fn subscribe(&mut self, key: K, subscription_id: usize) -> Subscription<K, F> {
|
||||||
Subscription {
|
Subscription {
|
||||||
key,
|
key,
|
||||||
|
@ -63,7 +81,7 @@ impl<K: Clone + Hash + Eq + Copy, F> CallbackCollection<K, F> {
|
||||||
|
|
||||||
// If this callback's subscription was dropped before the callback was
|
// If this callback's subscription was dropped before the callback was
|
||||||
// added, then just drop the callback.
|
// added, then just drop the callback.
|
||||||
if this.dropped_subscriptions.remove(&(key, subscription_id)) {
|
if this.clear_dropped_state(&key, subscription_id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,10 +92,12 @@ impl<K: Clone + Hash + Eq + Copy, F> CallbackCollection<K, F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(&mut self, key: K) {
|
pub fn remove(&mut self, key: K) {
|
||||||
let callbacks = self.internal.lock().callbacks.remove(&key);
|
|
||||||
|
|
||||||
// Drop these callbacks after releasing the lock, in case one of them
|
// Drop these callbacks after releasing the lock, in case one of them
|
||||||
// owns a subscription to this callback collection.
|
// owns a subscription to this callback collection.
|
||||||
|
let mut this = self.internal.lock();
|
||||||
|
let callbacks = this.callbacks.remove(&key);
|
||||||
|
this.dropped_subscriptions.remove(&key);
|
||||||
|
drop(this);
|
||||||
drop(callbacks);
|
drop(callbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,29 +111,26 @@ impl<K: Clone + Hash + Eq + Copy, F> CallbackCollection<K, F> {
|
||||||
if let Some(callbacks) = callbacks {
|
if let Some(callbacks) = callbacks {
|
||||||
for (subscription_id, mut callback) in callbacks {
|
for (subscription_id, mut callback) in callbacks {
|
||||||
// If this callback's subscription was dropped while invoking an
|
// If this callback's subscription was dropped while invoking an
|
||||||
// earlier callback, then just drop this callback.
|
// earlier callback, then just drop the callback.
|
||||||
if self
|
let mut this = self.internal.lock();
|
||||||
.internal
|
if this.clear_dropped_state(&key, subscription_id) {
|
||||||
.lock()
|
|
||||||
.dropped_subscriptions
|
|
||||||
.remove(&(key, subscription_id))
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if call_callback(&mut callback, cx) {
|
drop(this);
|
||||||
self.add_callback(key, subscription_id, callback);
|
let alive = call_callback(&mut callback, cx);
|
||||||
|
|
||||||
|
// If this callback's subscription was dropped while invoking the callback
|
||||||
|
// itself, or if the callback returns false, then just drop the callback.
|
||||||
|
let mut this = self.internal.lock();
|
||||||
|
if this.clear_dropped_state(&key, subscription_id) || !alive {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn gc(&mut self) {
|
this.callbacks
|
||||||
let mut this = self.internal.lock();
|
.entry(key)
|
||||||
|
.or_default()
|
||||||
for (key, id) in std::mem::take(&mut this.dropped_subscriptions) {
|
.insert(subscription_id, callback);
|
||||||
if let Some(callbacks) = this.callbacks.get_mut(&key) {
|
|
||||||
callbacks.remove(&id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,7 +167,9 @@ impl<K: Clone + Hash + Eq, F> Drop for Subscription<K, F> {
|
||||||
// removed later.
|
// removed later.
|
||||||
mapping
|
mapping
|
||||||
.dropped_subscriptions
|
.dropped_subscriptions
|
||||||
.insert((self.key.clone(), self.id));
|
.entry(self.key.clone())
|
||||||
|
.or_default()
|
||||||
|
.insert(self.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue