From 59f7f03d64cc78423537a108a69cd838e9cc5119 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Thu, 12 Dec 2019 01:01:11 +0200 Subject: [PATCH] ui: refactor watch thread spawning procedure - Remove unnecessary parameters from watch(), reload() - Add NewThread event that adds new threads in work_controller.static_threads hashmap - removed obsolete field State.threads - silence watch thread error notifications --- src/bin.rs | 4 +-- ui/src/conf/accounts.rs | 55 +++++++++++++++++------------------------ ui/src/state.rs | 42 ++++++++++--------------------- ui/src/types.rs | 2 +- 4 files changed, 39 insertions(+), 64 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index cabe55363..8f0f18998 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -373,8 +373,8 @@ fn run_app() -> Result<()> { state.check_accounts(); state.redraw(); }, - ThreadEvent::ThreadJoin(id) => { - state.join(id); + ThreadEvent::NewThread(id, name) => { + state.new_thread(id, name); }, } }, diff --git a/ui/src/conf/accounts.rs b/ui/src/conf/accounts.rs index b053fe832..109c88705 100644 --- a/ui/src/conf/accounts.rs +++ b/ui/src/conf/accounts.rs @@ -38,7 +38,7 @@ use melib::StackVec; use text_processing::GlobMatch; use crate::types::UIEvent::{self, EnvelopeRemove, EnvelopeRename, EnvelopeUpdate, Notification}; -use crate::{workers::WorkController, StatusEvent, ThreadEvent}; +use crate::{StatusEvent, ThreadEvent}; use crossbeam::Sender; use std::collections::VecDeque; use std::fs; @@ -162,6 +162,7 @@ pub struct Account { pub(crate) runtime_settings: AccountConf, pub(crate) backend: Arc>>, + sender: Sender, event_queue: VecDeque<(FolderHash, RefreshEvent)>, notify_fn: Arc, } @@ -245,6 +246,7 @@ impl Account { mut settings: AccountConf, map: &Backends, work_context: WorkContext, + sender: Sender, notify_fn: NotifyFn, ) -> Result { let s = settings.clone(); @@ -300,6 +302,7 @@ impl Account { settings, backend: Arc::new(RwLock::new(backend)), notify_fn, + sender, event_queue: VecDeque::with_capacity(8), }) @@ -514,16 +517,7 @@ impl Account { } Some(w) } - pub fn reload( - &mut self, - event: RefreshEvent, - folder_hash: FolderHash, - context: ( - &mut WorkController, - &Sender, - &mut VecDeque, - ), - ) -> Option { + pub fn reload(&mut self, event: RefreshEvent, folder_hash: FolderHash) -> Option { if !self.folders[&folder_hash].is_available() { self.event_queue.push_back((folder_hash, event)); return None; @@ -683,6 +677,7 @@ impl Account { } RefreshEventKind::Failure(e) => { debug!("RefreshEvent Failure: {}", e.to_string()); + /* context .1 .send(ThreadEvent::UIEvent(UIEvent::Notification( @@ -691,43 +686,39 @@ impl Account { Some(crate::types::NotificationType::ERROR), ))) .expect("Could not send event on main channel"); - self.watch(context); + */ + self.watch(); } } } None } - pub fn watch( - &self, - context: ( - &mut WorkController, - &Sender, - &mut VecDeque, - ), - ) { - let (work_controller, sender, replies) = context; - let sender = sender.clone(); + pub fn watch(&self) { + let sender_ = self.sender.clone(); let r = RefreshEventConsumer::new(Box::new(move |r| { - sender.send(ThreadEvent::from(r)).unwrap(); + sender_.send(ThreadEvent::from(r)).unwrap(); })); match self .backend .read() .unwrap() - .watch(r, work_controller.get_context()) + .watch(r, self.work_context.clone()) { Ok(id) => { - work_controller - .static_threads - .lock() - .unwrap() - .insert(id, format!("watching {}", self.name()).into()); + self.sender + .send(ThreadEvent::NewThread( + id, + format!("watching {}", self.name()).into(), + )) + .unwrap(); } Err(e) => { - replies.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage( - e.to_string(), - ))); + self.sender + .send(ThreadEvent::UIEvent(UIEvent::StatusEvent( + StatusEvent::DisplayMessage(e.to_string()), + ))) + .unwrap(); } } } diff --git a/ui/src/state.rs b/ui/src/state.rs index dd7881818..c1bed88f7 100644 --- a/ui/src/state.rs +++ b/ui/src/state.rs @@ -137,9 +137,6 @@ impl Context { pub fn is_online(&mut self, account_pos: usize) -> bool { let Context { - ref mut work_controller, - ref sender, - ref mut replies, ref mut accounts, ref mut mailbox_hashes, .. @@ -158,7 +155,7 @@ impl Context { * inform the main binary that refresh events arrived * - replies to report any failures to the user */ - accounts[account_pos].watch((work_controller, sender, replies)); + accounts[account_pos].watch(); } true } else { @@ -184,7 +181,6 @@ pub struct State { components: Vec>, pub context: Context, timer: thread::JoinHandle<()>, - threads: FnvHashMap, thread::JoinHandle<()>)>, } impl Drop for State { @@ -232,6 +228,7 @@ impl State { a_s.clone(), &backends, work_controller.get_context(), + sender.clone(), NotifyFn::new(Box::new(move |f: FolderHash| { sender .send(ThreadEvent::UIEvent(UIEvent::StartupCheck(f))) @@ -286,7 +283,6 @@ impl State { tx: input_thread.0, }, }, - threads: FnvHashMap::with_capacity_and_hasher(1, Default::default()), }; if s.context.settings.terminal.ascii_drawing { s.grid.set_ascii_drawing(true); @@ -319,41 +315,29 @@ impl State { return; } let Context { - ref mut work_controller, - ref sender, - ref mut replies, - ref mut accounts, - .. + ref mut accounts, .. } = &mut self.context; - if let Some(notification) = - accounts[idxa].reload(event, hash, (work_controller, sender, replies)) - { + if let Some(notification) = accounts[idxa].reload(event, hash) { if let UIEvent::Notification(_, _, _) = notification { self.rcv_event(UIEvent::MailboxUpdate((idxa, hash))); } self.rcv_event(notification); } } else { - if let melib::backends::RefreshEventKind::Failure(e) = event.kind() { - self.context - .sender - .send(ThreadEvent::UIEvent(UIEvent::Notification( - Some("watcher thread exited with error".to_string()), - e.to_string(), - Some(crate::types::NotificationType::ERROR), - ))) - .expect("Could not send event on main channel"); + if let melib::backends::RefreshEventKind::Failure(err) = event.kind() { + debug!(err); } } } - /// If an owned thread returns a `ThreadEvent::ThreadJoin` event to `State` then it must remove - /// the thread from its list and `join` it. - pub fn join(&mut self, id: thread::ThreadId) { - let (tx, handle) = self.threads.remove(&id).unwrap(); - tx.send(true).unwrap(); - handle.join().unwrap(); + pub fn new_thread(&mut self, id: thread::ThreadId, name: String) { + self.context + .work_controller + .static_threads + .lock() + .unwrap() + .insert(id, name.into()); } /// Switch back to the terminal's main screen (The command line the user sees before opening diff --git a/ui/src/types.rs b/ui/src/types.rs index 743e9fea6..b3ed0d0bc 100644 --- a/ui/src/types.rs +++ b/ui/src/types.rs @@ -46,7 +46,7 @@ pub enum StatusEvent { /// to the main process. #[derive(Debug)] pub enum ThreadEvent { - ThreadJoin(thread::ThreadId), + NewThread(thread::ThreadId, String), /// User input. Input(Key), /// User input and input as raw bytes.