make Observer::reset() mutable

use RwLock in ObserverBroadcast
This commit is contained in:
Michael Sippel 2021-01-11 01:18:32 +01:00
parent 86562614cc
commit 5007fdea3c
Signed by: senvas
GPG key ID: F96CF119C34B64A6
4 changed files with 34 additions and 39 deletions

View file

@ -1,7 +1,7 @@
use { use {
crate::core::View, crate::core::View,
std::{ std::{
ops::Deref, ops::{Deref, DerefMut},
sync::{Arc, Weak, RwLock} sync::{Arc, Weak, RwLock}
} }
}; };
@ -12,24 +12,22 @@ use {
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/ \*/
pub trait Observer<V: View + ?Sized> : Send + Sync { pub trait Observer<V: View + ?Sized> : Send + Sync {
fn reset(&self, view: Option<Arc<V>>) {} fn reset(&mut self, view: Option<Arc<V>>) {}
fn notify(&self, msg: &V::Msg); fn notify(&self, msg: &V::Msg);
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<V: View + ?Sized, O: Observer<V>> Observer<V> for RwLock<O> { impl<V: View + ?Sized, O: Observer<V>> Observer<V> for Arc<RwLock<O>> {
fn reset(&mut self, view: Option<Arc<V>>) {
self.write().unwrap().reset(view);
}
fn notify(&self, msg: &V::Msg) { fn notify(&self, msg: &V::Msg) {
self.read().unwrap().notify(&msg); self.read().unwrap().notify(&msg);
} }
} }
impl<V: View + ?Sized, O: Observer<V>> Observer<V> for Arc<O> {
fn notify(&self, msg: &V::Msg) {
self.deref().notify(&msg);
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub trait ObserverExt<V: View + ?Sized> : Observer<V> { pub trait ObserverExt<V: View + ?Sized> : Observer<V> {
@ -51,7 +49,7 @@ impl<V: View + ?Sized, T: Observer<V>> ObserverExt<V> for T {
\*/ \*/
pub struct ObserverBroadcast<V: View + ?Sized> { pub struct ObserverBroadcast<V: View + ?Sized> {
observers: Vec<Weak<dyn Observer<V>>> observers: Vec<Weak<RwLock<dyn Observer<V>>>>
} }
impl<V: View + ?Sized> ObserverBroadcast<V> { impl<V: View + ?Sized> ObserverBroadcast<V> {
@ -61,7 +59,7 @@ impl<V: View + ?Sized> ObserverBroadcast<V> {
} }
} }
pub fn add_observer(&mut self, obs: Weak<dyn Observer<V>>) { pub fn add_observer(&mut self, obs: Weak<RwLock<dyn Observer<V>>>) {
self.cleanup(); self.cleanup();
self.observers.push(obs); self.observers.push(obs);
} }
@ -70,21 +68,21 @@ impl<V: View + ?Sized> ObserverBroadcast<V> {
self.observers.retain(|o| o.strong_count() > 0); self.observers.retain(|o| o.strong_count() > 0);
} }
fn iter(&self) -> impl Iterator<Item = Arc<dyn Observer<V>>> + '_ { fn iter(&self) -> impl Iterator<Item = Arc<RwLock<dyn Observer<V>>>> + '_ {
self.observers.iter().filter_map(|o| o.upgrade()) self.observers.iter().filter_map(|o| o.upgrade())
} }
} }
impl<V: View + ?Sized> Observer<V> for ObserverBroadcast<V> { impl<V: View + ?Sized> Observer<V> for ObserverBroadcast<V> {
fn reset(&self, view: Option<Arc<V>>) { fn reset(&mut self, view: Option<Arc<V>>) {
for o in self.iter() { for o in self.iter() {
o.reset(view.clone()); o.write().unwrap().reset(view.clone());
} }
} }
fn notify(&self, msg: &V::Msg) { fn notify(&self, msg: &V::Msg) {
for o in self.iter() { for o in self.iter() {
o.notify(&msg); o.read().unwrap().notify(&msg);
} }
} }
} }
@ -141,7 +139,7 @@ impl<V, F> Observer<V> for ResetFnObserver<V, F>
where V: View + ?Sized, where V: View + ?Sized,
F: Fn(Option<Arc<V>>) + Send + Sync { F: Fn(Option<Arc<V>>) + Send + Sync {
fn notify(&self, msg: &V::Msg) {} fn notify(&self, msg: &V::Msg) {}
fn reset(&self, view: Option<Arc<V>>) { fn reset(&mut self, view: Option<Arc<V>>) {
(self.f)(view); (self.f)(view);
} }
} }

View file

@ -41,12 +41,12 @@ impl<V: View + ?Sized> ViewPort<V> {
pub fn set_view(&self, view: Option<Arc<V>>) { pub fn set_view(&self, view: Option<Arc<V>>) {
*self.view.write().unwrap() = view.clone(); *self.view.write().unwrap() = view.clone();
self.observers.read().unwrap().reset(view); self.observers.write().unwrap().reset(view);
} }
pub fn add_observer(&self, observer: Arc<dyn Observer<V>>) { pub fn add_observer(&self, observer: Arc<RwLock<dyn Observer<V>>>) {
self.observers.write().unwrap().add_observer(Arc::downgrade(&observer)); self.observers.write().unwrap().add_observer(Arc::downgrade(&observer));
observer.reset(self.view.read().unwrap().clone()); observer.write().unwrap().reset(self.view.read().unwrap().clone());
} }
pub fn inner(&self) -> InnerViewPort<V> { pub fn inner(&self) -> InnerViewPort<V> {
@ -106,7 +106,7 @@ impl<V: View + ?Sized + 'static> OuterViewPort<V> {
self.0.view.clone() self.0.view.clone()
} }
pub fn add_observer(&self, observer: Arc<dyn Observer<V>>) -> Arc<RwLock<Option<Arc<V>>>> { pub fn add_observer(&self, observer: Arc<RwLock<dyn Observer<V>>>) -> Arc<RwLock<Option<Arc<V>>>> {
self.0.add_observer(observer); self.0.add_observer(observer);
self.get_view_arc() self.get_view_arc()
} }

View file

@ -15,19 +15,17 @@ use {
struct CompositeLayer { struct CompositeLayer {
comp: Weak<RwLock<TerminalCompositeView>>, comp: Weak<RwLock<TerminalCompositeView>>,
idx: usize, idx: usize
view: RwLock<Option<Arc<dyn TerminalView>>>
} }
impl Observer<dyn TerminalView> for CompositeLayer { impl Observer<dyn TerminalView> for CompositeLayer {
fn reset(&self, view: Option<Arc<dyn TerminalView>>) { fn reset(&mut self, view: Option<Arc<dyn TerminalView>>) {
let comp = self.comp.upgrade().unwrap(); let comp = self.comp.upgrade().unwrap();
let mut c = comp.write().unwrap(); let mut c = comp.write().unwrap();
{ {
let mut v = self.view.write().unwrap(); let old_view = c.layers[&self.idx].1.clone();
let old_view = v.clone(); c.layers.get_mut(&self.idx).unwrap().1 = view.clone();
*v = view.clone();
if let Some(old_view) = old_view { if let Some(old_view) = old_view {
if let Some(range) = old_view.range() { if let Some(range) = old_view.range() {
@ -35,7 +33,7 @@ impl Observer<dyn TerminalView> for CompositeLayer {
} }
} }
if let Some(view) = v.as_ref() { if let Some(view) = view.as_ref() {
if let Some(range) = view.range() { if let Some(range) = view.range() {
c.cast.notify_each(GridWindowIterator::from(range)); c.cast.notify_each(GridWindowIterator::from(range));
} }
@ -55,7 +53,7 @@ impl Observer<dyn TerminalView> for CompositeLayer {
pub struct TerminalCompositeView { pub struct TerminalCompositeView {
idx_count: usize, idx_count: usize,
layers: HashMap<usize, Arc<CompositeLayer>>, layers: HashMap<usize, (Arc<RwLock<CompositeLayer>>, Option<Arc<dyn TerminalView>>)>,
range: Option<Range<Point2<i16>>>, range: Option<Range<Point2<i16>>>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>> cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>
} }
@ -73,7 +71,7 @@ impl TerminalCompositeView {
Some(new_range), Some(new_range),
Some(old_range) Some(old_range)
) = ( ) = (
if let Some(view) = layer.view.read().unwrap().clone() { if let Some(view) = layer.1.as_ref() {
view.range().clone() view.range().clone()
} else { } else {
None None
@ -106,7 +104,7 @@ impl ImplIndexView for TerminalCompositeView {
for idx in 0 .. self.idx_count { for idx in 0 .. self.idx_count {
if let Some(l) = self.layers.get(&idx) { if let Some(l) = self.layers.get(&idx) {
if let Some(view) = l.view.read().unwrap().as_ref() { if let Some(view) = l.1.as_ref() {
if let Some(range) = view.range() { if let Some(range) = view.range() {
if pos.x < range.start.x || if pos.x < range.start.x ||
pos.x >= range.end.x || pos.x >= range.end.x ||
@ -160,13 +158,12 @@ impl TerminalCompositor {
let idx = comp.idx_count; let idx = comp.idx_count;
comp.idx_count += 1; comp.idx_count += 1;
let layer = Arc::new(CompositeLayer { let layer = Arc::new(RwLock::new(CompositeLayer {
comp: Arc::downgrade(&self.view), comp: Arc::downgrade(&self.view),
idx: idx, idx: idx
view: RwLock::new(None) }));
});
comp.layers.insert(idx, layer.clone()); comp.layers.insert(idx, (layer.clone(), None));
drop(comp); drop(comp);
v.add_observer(layer); v.add_observer(layer);

View file

@ -44,7 +44,7 @@ pub enum TerminalEvent {
pub struct Terminal { pub struct Terminal {
writer: Arc<TermOutWriter>, writer: Arc<TermOutWriter>,
observer: Arc<TermOutObserver>, observer: Arc<RwLock<TermOutObserver>>,
events: ChannelReceiver<Vec<TerminalEvent>>, events: ChannelReceiver<Vec<TerminalEvent>>,
_signal_handle: signal_hook_async_std::Handle _signal_handle: signal_hook_async_std::Handle
@ -62,10 +62,10 @@ impl Terminal {
view: port.get_view_arc() view: port.get_view_arc()
}); });
let observer = Arc::new(TermOutObserver { let observer = Arc::new(RwLock::new(TermOutObserver {
dirty_pos_tx, dirty_pos_tx,
writer: writer.clone() writer: writer.clone()
}); }));
port.add_observer(observer.clone()); port.add_observer(observer.clone());
@ -122,7 +122,7 @@ struct TermOutObserver {
} }
impl Observer<dyn TerminalView> for TermOutObserver { impl Observer<dyn TerminalView> for TermOutObserver {
fn reset(&self, view: Option<Arc<dyn TerminalView>>) { fn reset(&mut self, view: Option<Arc<dyn TerminalView>>) {
self.writer.reset(); self.writer.reset();
let (w, h) = termion::terminal_size().unwrap(); let (w, h) = termion::terminal_size().unwrap();