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 {
crate::core::View,
std::{
ops::Deref,
ops::{Deref, DerefMut},
sync::{Arc, Weak, RwLock}
}
};
@ -12,24 +12,22 @@ use {
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/
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);
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
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) {
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> {
@ -51,7 +49,7 @@ impl<V: View + ?Sized, T: Observer<V>> ObserverExt<V> for T {
\*/
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> {
@ -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.observers.push(obs);
}
@ -70,21 +68,21 @@ impl<V: View + ?Sized> ObserverBroadcast<V> {
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())
}
}
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() {
o.reset(view.clone());
o.write().unwrap().reset(view.clone());
}
}
fn notify(&self, msg: &V::Msg) {
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,
F: Fn(Option<Arc<V>>) + Send + Sync {
fn notify(&self, msg: &V::Msg) {}
fn reset(&self, view: Option<Arc<V>>) {
fn reset(&mut self, view: Option<Arc<V>>) {
(self.f)(view);
}
}

View file

@ -41,12 +41,12 @@ impl<V: View + ?Sized> ViewPort<V> {
pub fn set_view(&self, view: Option<Arc<V>>) {
*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));
observer.reset(self.view.read().unwrap().clone());
observer.write().unwrap().reset(self.view.read().unwrap().clone());
}
pub fn inner(&self) -> InnerViewPort<V> {
@ -106,7 +106,7 @@ impl<V: View + ?Sized + 'static> OuterViewPort<V> {
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.get_view_arc()
}

View file

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

View file

@ -44,7 +44,7 @@ pub enum TerminalEvent {
pub struct Terminal {
writer: Arc<TermOutWriter>,
observer: Arc<TermOutObserver>,
observer: Arc<RwLock<TermOutObserver>>,
events: ChannelReceiver<Vec<TerminalEvent>>,
_signal_handle: signal_hook_async_std::Handle
@ -62,10 +62,10 @@ impl Terminal {
view: port.get_view_arc()
});
let observer = Arc::new(TermOutObserver {
let observer = Arc::new(RwLock::new(TermOutObserver {
dirty_pos_tx,
writer: writer.clone()
});
}));
port.add_observer(observer.clone());
@ -122,7 +122,7 @@ struct 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();
let (w, h) = termion::terminal_size().unwrap();