From f9a38200ce2511e8b848c325792d244b4fb16b1b Mon Sep 17 00:00:00 2001 From: Jiayi Zhao Date: Tue, 5 Feb 2019 21:29:45 -0500 Subject: incomplete rework on file operation threads - in an attempt to fix bug that crashes program after a paste when threads are not waited for --- src/joshuto.rs | 41 ++++++++++++--------- src/joshuto/command.rs | 2 +- src/joshuto/command/file_operations.rs | 66 +++++++++++++++++++++++----------- src/joshuto/context.rs | 8 ++--- src/joshuto/ui.rs | 4 +-- 5 files changed, 74 insertions(+), 47 deletions(-) diff --git a/src/joshuto.rs b/src/joshuto.rs index 007362e..c9088ca 100644 --- a/src/joshuto.rs +++ b/src/joshuto.rs @@ -68,29 +68,39 @@ fn recurse_get_keycommand<'a>( } fn process_threads(context: &mut JoshutoContext) { - let wait_duration: time::Duration = time::Duration::from_millis(100); - let mut something_finished = false; - for i in 0..context.threads.len() { - if let Ok(progress_info) = &context.threads[i].0.recv_timeout(wait_duration) { - if progress_info.bytes_finished == progress_info.total_bytes { - let (_, chandle) = context.threads.remove(i); - chandle.join().unwrap(); - ncurses::werase(context.views.bot_win.win); - something_finished = true; - break; - } else { + let thread_wait_duration: time::Duration = time::Duration::from_millis(100); + + let mut i: usize = 0; + while i < context.threads.len() { + match &context.threads[i].recv_timeout(&thread_wait_duration) { + Ok(progress_info) => { let percent = (progress_info.bytes_finished as f64 / progress_info.total_bytes as f64) as f32; ui::draw_progress_bar(&context.views.bot_win, percent); ncurses::wnoutrefresh(context.views.bot_win.win); ncurses::doupdate(); + i = i + 1; + } + Err(std::sync::mpsc::RecvTimeoutError::Disconnected) => { + ncurses::werase(context.views.bot_win.win); + let thread = context.threads.swap_remove(i); + eprintln!("joining thread"); + ncurses::doupdate(); + thread.handle.join().unwrap(); + let (tab_src, tab_dest) = (thread.tab_src, thread.tab_dest); + if tab_src < context.tabs.len() { + context.tabs[tab_src].reload_contents(&context.config_t.sort_type); + } + if tab_dest != tab_src && tab_dest < context.tabs.len() { + context.tabs[tab_dest].reload_contents(&context.config_t.sort_type); + } + eprintln!("done refreshing"); + } + Err(std::sync::mpsc::RecvTimeoutError::Timeout) => { + i = i + 1; } } } - if something_finished { - // command::ReloadDirList::reload(context); - ncurses::doupdate(); - } } fn resize_handler(context: &mut JoshutoContext) { @@ -110,7 +120,6 @@ fn resize_handler(context: &mut JoshutoContext) { pub fn run(config_t: config::JoshutoConfig, keymap_t: config::JoshutoKeymap) { ui::init_ncurses(); - ncurses::doupdate(); let mut context = context::JoshutoContext::new(config_t); command::NewTab::new_tab(&mut context); diff --git a/src/joshuto/command.rs b/src/joshuto/command.rs index fa3b3e4..0099d8c 100644 --- a/src/joshuto/command.rs +++ b/src/joshuto/command.rs @@ -22,7 +22,7 @@ pub use self::cursor_move::{ CursorMove, CursorMoveEnd, CursorMoveHome, CursorMovePageDown, CursorMovePageUp, }; pub use self::delete_files::DeleteFiles; -pub use self::file_operations::{CopyFiles, CutFiles, PasteFiles}; +pub use self::file_operations::{CopyFiles, CutFiles, FileOperationThread, PasteFiles}; pub use self::new_directory::NewDirectory; pub use self::open_file::{OpenFile, OpenFileWith}; pub use self::parent_directory::ParentDirectory; diff --git a/src/joshuto/command/file_operations.rs b/src/joshuto/command/file_operations.rs index 207cd5c..b96dee0 100644 --- a/src/joshuto/command/file_operations.rs +++ b/src/joshuto/command/file_operations.rs @@ -4,6 +4,7 @@ extern crate ncurses; use std::path; use std::sync; use std::thread; +use std::time; use joshuto::command::{self, JoshutoCommand, JoshutoRunnable, ProgressInfo}; use joshuto::context::JoshutoContext; @@ -13,6 +14,23 @@ use joshuto::structs::JoshutoDirList; lazy_static! { static ref selected_files: sync::Mutex> = sync::Mutex::new(vec![]); static ref fileop: sync::Mutex = sync::Mutex::new(FileOp::Copy); + static ref tab_src: sync::Mutex = sync::Mutex::new(0); +} + +pub struct FileOperationThread { + pub tab_src: usize, + pub tab_dest: usize, + pub handle: thread::JoinHandle, + pub recv: sync::mpsc::Receiver, +} + +impl FileOperationThread { + pub fn recv_timeout( + &self, + wait_duration: &time::Duration, + ) -> Result { + self.recv.recv_timeout(*wait_duration) + } } fn set_file_op(operation: FileOp) { @@ -20,6 +38,11 @@ fn set_file_op(operation: FileOp) { *data = operation; } +fn set_tab_src(tab_index: usize) { + let mut data = tab_src.lock().unwrap(); + *data = tab_index; +} + fn repopulated_selected_files(dirlist: &JoshutoDirList) -> bool { if let Some(contents) = command::collect_selected_paths(dirlist) { let mut data = selected_files.lock().unwrap(); @@ -62,10 +85,11 @@ impl std::fmt::Display for CutFiles { impl JoshutoRunnable for CutFiles { fn execute(&self, context: &mut JoshutoContext) { - let curr_tab = &context.tabs[context.curr_tab_index]; + let curr_tab = context.curr_tab_ref(); if let Some(s) = curr_tab.curr_list.as_ref() { if repopulated_selected_files(s) { set_file_op(FileOp::Cut); + set_tab_src(context.curr_tab_index); } } } @@ -93,10 +117,11 @@ impl std::fmt::Display for CopyFiles { impl JoshutoRunnable for CopyFiles { fn execute(&self, context: &mut JoshutoContext) { - let curr_tab = &context.tabs[context.curr_tab_index]; + let curr_tab = context.curr_tab_ref(); if let Some(s) = curr_tab.curr_list.as_ref() { if repopulated_selected_files(s) { set_file_op(FileOp::Copy); + set_tab_src(context.curr_tab_index); } } } @@ -154,10 +179,7 @@ impl PasteFiles { if let Ok(metadata) = std::fs::symlink_metadata(path) { if metadata.is_dir() { destination.pop(); - match fs_extra::dir::move_dir(&path, &destination, &options) { - Ok(_) => {} - Err(e) => eprintln!("dir: {}", e), - } + fs_extra::dir::move_dir(&path, &destination, &options).unwrap(); } else { if let Ok(_) = std::fs::copy(&path, &destination) { std::fs::remove_file(&path).unwrap(); @@ -173,11 +195,9 @@ impl PasteFiles { progress_info.bytes_finished = progress_info.bytes_finished + 1; tx.send(progress_info.clone()).unwrap(); } - paths.clear(); 0 }); - (rx, child) } @@ -238,21 +258,25 @@ impl JoshutoRunnable for PasteFiles { fn execute(&self, context: &mut JoshutoContext) { let file_operation = fileop.lock().unwrap(); - let curr_tab = &mut context.tabs[context.curr_tab_index]; - let cprocess = match *file_operation { + let tab_dest = context.curr_tab_index; + let curr_tab = &context.tabs[tab_dest]; + let tab_src_index: usize; + { + tab_src_index = *tab_src.lock().unwrap(); + } + + let (recv, handle) = match *file_operation { FileOp::Copy => self.copy(&curr_tab.curr_path), FileOp::Cut => self.cut(&curr_tab.curr_path), }; - context.threads.push(cprocess); - - curr_tab.reload_contents(&context.config_t.sort_type); - curr_tab.refresh( - &context.views, - &context.config_t, - &context.username, - &context.hostname, - ); - ncurses::timeout(0); - ncurses::doupdate(); + + let thread = FileOperationThread { + tab_src: tab_src_index, + tab_dest, + handle, + recv, + }; + + context.threads.push(thread); } } diff --git a/src/joshuto/context.rs b/src/joshuto/context.rs index b1b8fe2..361676c 100644 --- a/src/joshuto/context.rs +++ b/src/joshuto/context.rs @@ -1,7 +1,6 @@ -use std::sync; use std::thread; -use joshuto::command; +use joshuto::command::FileOperationThread; use joshuto::config; use joshuto::tab::JoshutoTab; use joshuto::window::JoshutoView; @@ -9,10 +8,7 @@ use joshuto::window::JoshutoView; pub struct JoshutoContext { pub username: String, pub hostname: String, - pub threads: Vec<( - sync::mpsc::Receiver, - thread::JoinHandle, - )>, + pub threads: Vec, pub views: JoshutoView, pub curr_tab_index: usize, pub tabs: Vec, diff --git a/src/joshuto/ui.rs b/src/joshuto/ui.rs index 675480d..6bd497f 100644 --- a/src/joshuto/ui.rs +++ b/src/joshuto/ui.rs @@ -16,9 +16,7 @@ pub const ERR_COLOR: i16 = 240; pub const EMPTY_COLOR: i16 = 241; pub fn init_ncurses() { - let locale_conf = ncurses::LcCategory::all; - - ncurses::setlocale(locale_conf, ""); + ncurses::setlocale(ncurses::LcCategory::all, ""); ncurses::initscr(); ncurses::cbreak(); -- cgit v1.2.3