From 7ac42f12468569e87b59298dafeab6bf2ac9a881 Mon Sep 17 00:00:00 2001 From: Yjn024 Date: Sun, 13 Aug 2023 19:36:42 +0800 Subject: [PATCH] invoker cache --- src/util/mod.rs | 75 +++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 50 deletions(-) diff --git a/src/util/mod.rs b/src/util/mod.rs index 587bb81..874e9f7 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -282,57 +282,53 @@ impl Freeze for T { } } -pub struct Event +pub struct Event where T: ?Sized + 'static, Phase: Ord, - Ivk: Fn(Vec<&'static T>) -> Box, { - listeners: parking_lot::RwLock>, - invoker_factory: Ivk, + listeners_and_cache: parking_lot::RwLock<(Vec<(Phase, *const T)>, Option>)>, + invoker_factory: fn(Vec<&'static T>) -> Box, dirty: std::sync::atomic::AtomicBool, } -impl Event +impl Event where T: ?Sized, Phase: Ord, - Ivk: Fn(Vec<&'static T>) -> Box, { - pub const fn new(invoker_factory: Ivk) -> Self { + pub const fn new(invoker_factory: fn(Vec<&'static T>) -> Box) -> Self { Self { - listeners: parking_lot::RwLock::new(Vec::new()), + listeners_and_cache: parking_lot::RwLock::new((Vec::new(), None)), invoker_factory, dirty: std::sync::atomic::AtomicBool::new(false), } } - pub fn invoker<'a>(&'a self) -> EventInvokerGuard<'a, T> { + pub fn invoker(&self) -> &T { if self.dirty.load(std::sync::atomic::Ordering::Acquire) { - self.listeners - .write() - .sort_by(|e0, e1| Phase::cmp(&e0.0, &e1.0)); + let mut write_guard = self.listeners_and_cache.write(); + write_guard.0.sort_by(|e0, e1| Phase::cmp(&e0.0, &e1.0)); self.dirty .store(false, std::sync::atomic::Ordering::Release); - } - - let vec: Vec<_> = self - .listeners - .read() - .iter() - .map(|e| unsafe { &*e.1 }) - .collect(); - EventInvokerGuard { - value: Box::leak((self.invoker_factory)(vec)), - _ptr: 0 as *mut (), + write_guard.1 = Some((self.invoker_factory)( + write_guard.0.iter().map(|e| unsafe { &*e.1 }).collect(), + )); + } else if self.listeners_and_cache.read().1.is_none() { + self.listeners_and_cache.write().1 = Some((self.invoker_factory)(Vec::new())) } + + unsafe { &*(self.listeners_and_cache.read().1.as_ref().unwrap().deref() as *const T) } } pub fn register_with_phase(&mut self, listener: Box, phase: Phase) { - self.listeners.get_mut().push((phase, Box::leak(listener))); + self.listeners_and_cache + .get_mut() + .0 + .push((phase, Box::leak(listener))); if !self.dirty.load(std::sync::atomic::Ordering::Acquire) { self.dirty.store(true, std::sync::atomic::Ordering::Release); @@ -340,26 +336,24 @@ where } } -impl Event +impl Event where T: ?Sized, Phase: Ord + Default, - Ivk: Fn(Vec<&'static T>) -> Box, { pub fn register(&mut self, listener: Box) { self.register_with_phase(listener, Default::default()) } } -impl Drop for Event +impl Drop for Event where T: ?Sized, Phase: Ord, - Ivk: Fn(Vec<&'static T>) -> Box, { fn drop(&mut self) { let mut vec = Vec::new(); - std::mem::swap(self.listeners.get_mut(), &mut vec); + std::mem::swap(&mut self.listeners_and_cache.get_mut().0, &mut vec); for value in vec { let _ = unsafe { Box::from_raw(value.1 as *mut T) }; @@ -367,38 +361,19 @@ where } } -unsafe impl Send for Event +unsafe impl Send for Event where T: ?Sized, Phase: Ord + Send, - Ivk: Fn(Vec<&'static T>) -> Box + Send, { } -unsafe impl Sync for Event +unsafe impl Sync for Event where T: ?Sized, Phase: Ord + Sync, - Ivk: Fn(Vec<&'static T>) -> Box + Sync, { } -pub struct EventInvokerGuard<'a, T: ?Sized> { - value: &'a T, - _ptr: *mut (), -} - -impl<'a, T: ?Sized> EventInvokerGuard<'a, T> { - pub fn as_ref(&self) -> &'a T { - self.value - } -} - -impl Drop for EventInvokerGuard<'_, T> { - fn drop(&mut self) { - let _ = unsafe { Box::from_raw(self.value as *const T as *mut T) }; - } -} - #[cfg(test)] mod event_tests {}