mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 13:51:31 +00:00
Shutdown/cancelation story for main cargo watch thread
This commit is contained in:
parent
a2d10694cc
commit
02ce5bbf6b
1 changed files with 32 additions and 15 deletions
|
@ -32,12 +32,13 @@ pub struct CheckOptions {
|
||||||
/// CheckWatcher wraps the shared state and communication machinery used for
|
/// CheckWatcher wraps the shared state and communication machinery used for
|
||||||
/// running `cargo check` (or other compatible command) and providing
|
/// running `cargo check` (or other compatible command) and providing
|
||||||
/// diagnostics based on the output.
|
/// diagnostics based on the output.
|
||||||
|
/// The spawned thread is shut down when this struct is dropped.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CheckWatcher {
|
pub struct CheckWatcher {
|
||||||
pub task_recv: Receiver<CheckTask>,
|
pub task_recv: Receiver<CheckTask>,
|
||||||
pub cmd_send: Sender<CheckCommand>,
|
pub cmd_send: Sender<CheckCommand>,
|
||||||
pub shared: Arc<RwLock<CheckWatcherSharedState>>,
|
pub shared: Arc<RwLock<CheckWatcherSharedState>>,
|
||||||
handle: JoinHandle<()>,
|
handle: Option<JoinHandle<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CheckWatcher {
|
impl CheckWatcher {
|
||||||
|
@ -52,8 +53,7 @@ impl CheckWatcher {
|
||||||
let mut check = CheckWatcherState::new(options, workspace_root, shared_);
|
let mut check = CheckWatcherState::new(options, workspace_root, shared_);
|
||||||
check.run(&task_send, &cmd_recv);
|
check.run(&task_send, &cmd_recv);
|
||||||
});
|
});
|
||||||
|
CheckWatcher { task_recv, cmd_send, handle: Some(handle), shared }
|
||||||
CheckWatcher { task_recv, cmd_send, handle, shared }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Schedule a re-start of the cargo check worker.
|
/// Schedule a re-start of the cargo check worker.
|
||||||
|
@ -62,13 +62,21 @@ impl CheckWatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CheckWatcherState {
|
impl std::ops::Drop for CheckWatcher {
|
||||||
options: CheckOptions,
|
fn drop(&mut self) {
|
||||||
workspace_root: PathBuf,
|
if let Some(handle) = self.handle.take() {
|
||||||
running: bool,
|
// Replace our reciever with dummy one, so we can drop and close the
|
||||||
watcher: WatchThread,
|
// one actually communicating with the thread
|
||||||
last_update_req: Option<Instant>,
|
let recv = std::mem::replace(&mut self.task_recv, crossbeam_channel::never());
|
||||||
shared: Arc<RwLock<CheckWatcherSharedState>>,
|
|
||||||
|
// Dropping the original reciever finishes the thread loop
|
||||||
|
drop(recv);
|
||||||
|
|
||||||
|
// Join the thread, it should finish shortly. We don't really care
|
||||||
|
// whether it panicked, so it is safe to ignore the result
|
||||||
|
let _ = handle.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -153,6 +161,14 @@ pub enum CheckCommand {
|
||||||
Update,
|
Update,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CheckWatcherState {
|
||||||
|
options: CheckOptions,
|
||||||
|
workspace_root: PathBuf,
|
||||||
|
watcher: WatchThread,
|
||||||
|
last_update_req: Option<Instant>,
|
||||||
|
shared: Arc<RwLock<CheckWatcherSharedState>>,
|
||||||
|
}
|
||||||
|
|
||||||
impl CheckWatcherState {
|
impl CheckWatcherState {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
options: CheckOptions,
|
options: CheckOptions,
|
||||||
|
@ -163,7 +179,6 @@ impl CheckWatcherState {
|
||||||
CheckWatcherState {
|
CheckWatcherState {
|
||||||
options,
|
options,
|
||||||
workspace_root,
|
workspace_root,
|
||||||
running: false,
|
|
||||||
watcher,
|
watcher,
|
||||||
last_update_req: None,
|
last_update_req: None,
|
||||||
shared,
|
shared,
|
||||||
|
@ -171,19 +186,21 @@ impl CheckWatcherState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self, task_send: &Sender<CheckTask>, cmd_recv: &Receiver<CheckCommand>) {
|
pub fn run(&mut self, task_send: &Sender<CheckTask>, cmd_recv: &Receiver<CheckCommand>) {
|
||||||
self.running = true;
|
loop {
|
||||||
while self.running {
|
|
||||||
select! {
|
select! {
|
||||||
recv(&cmd_recv) -> cmd => match cmd {
|
recv(&cmd_recv) -> cmd => match cmd {
|
||||||
Ok(cmd) => self.handle_command(cmd),
|
Ok(cmd) => self.handle_command(cmd),
|
||||||
Err(RecvError) => {
|
Err(RecvError) => {
|
||||||
// Command channel has closed, so shut down
|
// Command channel has closed, so shut down
|
||||||
self.running = false;
|
break;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
recv(self.watcher.message_recv) -> msg => match msg {
|
recv(self.watcher.message_recv) -> msg => match msg {
|
||||||
Ok(msg) => self.handle_message(msg, task_send),
|
Ok(msg) => self.handle_message(msg, task_send),
|
||||||
Err(RecvError) => {},
|
Err(RecvError) => {
|
||||||
|
// Task channel has closed, so shut down
|
||||||
|
break;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue