aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_cargo_watch
diff options
context:
space:
mode:
authorEmil Lauridsen <[email protected]>2019-12-27 10:43:05 +0000
committerEmil Lauridsen <[email protected]>2019-12-27 10:43:05 +0000
commit02ce5bbf6b46a67c3fc12b964de204b8130f1b10 (patch)
tree171733bb09f299cb50d8bb45aba1e86c14390acd /crates/ra_cargo_watch
parenta2d10694ccfcd12dad8796fc86966ea10ca3fc01 (diff)
Shutdown/cancelation story for main cargo watch thread
Diffstat (limited to 'crates/ra_cargo_watch')
-rw-r--r--crates/ra_cargo_watch/src/lib.rs47
1 files changed, 32 insertions, 15 deletions
diff --git a/crates/ra_cargo_watch/src/lib.rs b/crates/ra_cargo_watch/src/lib.rs
index 70afd7f8a..4af26ff8c 100644
--- a/crates/ra_cargo_watch/src/lib.rs
+++ b/crates/ra_cargo_watch/src/lib.rs
@@ -32,12 +32,13 @@ pub struct CheckOptions {
32/// CheckWatcher wraps the shared state and communication machinery used for 32/// CheckWatcher wraps the shared state and communication machinery used for
33/// running `cargo check` (or other compatible command) and providing 33/// running `cargo check` (or other compatible command) and providing
34/// diagnostics based on the output. 34/// diagnostics based on the output.
35/// The spawned thread is shut down when this struct is dropped.
35#[derive(Debug)] 36#[derive(Debug)]
36pub struct CheckWatcher { 37pub struct CheckWatcher {
37 pub task_recv: Receiver<CheckTask>, 38 pub task_recv: Receiver<CheckTask>,
38 pub cmd_send: Sender<CheckCommand>, 39 pub cmd_send: Sender<CheckCommand>,
39 pub shared: Arc<RwLock<CheckWatcherSharedState>>, 40 pub shared: Arc<RwLock<CheckWatcherSharedState>>,
40 handle: JoinHandle<()>, 41 handle: Option<JoinHandle<()>>,
41} 42}
42 43
43impl CheckWatcher { 44impl CheckWatcher {
@@ -52,8 +53,7 @@ impl CheckWatcher {
52 let mut check = CheckWatcherState::new(options, workspace_root, shared_); 53 let mut check = CheckWatcherState::new(options, workspace_root, shared_);
53 check.run(&task_send, &cmd_recv); 54 check.run(&task_send, &cmd_recv);
54 }); 55 });
55 56 CheckWatcher { task_recv, cmd_send, handle: Some(handle), shared }
56 CheckWatcher { task_recv, cmd_send, handle, shared }
57 } 57 }
58 58
59 /// Schedule a re-start of the cargo check worker. 59 /// Schedule a re-start of the cargo check worker.
@@ -62,13 +62,21 @@ impl CheckWatcher {
62 } 62 }
63} 63}
64 64
65pub struct CheckWatcherState { 65impl std::ops::Drop for CheckWatcher {
66 options: CheckOptions, 66 fn drop(&mut self) {
67 workspace_root: PathBuf, 67 if let Some(handle) = self.handle.take() {
68 running: bool, 68 // Replace our reciever with dummy one, so we can drop and close the
69 watcher: WatchThread, 69 // one actually communicating with the thread
70 last_update_req: Option<Instant>, 70 let recv = std::mem::replace(&mut self.task_recv, crossbeam_channel::never());
71 shared: Arc<RwLock<CheckWatcherSharedState>>, 71
72 // Dropping the original reciever finishes the thread loop
73 drop(recv);
74
75 // Join the thread, it should finish shortly. We don't really care
76 // whether it panicked, so it is safe to ignore the result
77 let _ = handle.join();
78 }
79 }
72} 80}
73 81
74#[derive(Debug)] 82#[derive(Debug)]
@@ -153,6 +161,14 @@ pub enum CheckCommand {
153 Update, 161 Update,
154} 162}
155 163
164struct CheckWatcherState {
165 options: CheckOptions,
166 workspace_root: PathBuf,
167 watcher: WatchThread,
168 last_update_req: Option<Instant>,
169 shared: Arc<RwLock<CheckWatcherSharedState>>,
170}
171
156impl CheckWatcherState { 172impl CheckWatcherState {
157 pub fn new( 173 pub fn new(
158 options: CheckOptions, 174 options: CheckOptions,
@@ -163,7 +179,6 @@ impl CheckWatcherState {
163 CheckWatcherState { 179 CheckWatcherState {
164 options, 180 options,
165 workspace_root, 181 workspace_root,
166 running: false,
167 watcher, 182 watcher,
168 last_update_req: None, 183 last_update_req: None,
169 shared, 184 shared,
@@ -171,19 +186,21 @@ impl CheckWatcherState {
171 } 186 }
172 187
173 pub fn run(&mut self, task_send: &Sender<CheckTask>, cmd_recv: &Receiver<CheckCommand>) { 188 pub fn run(&mut self, task_send: &Sender<CheckTask>, cmd_recv: &Receiver<CheckCommand>) {
174 self.running = true; 189 loop {
175 while self.running {
176 select! { 190 select! {
177 recv(&cmd_recv) -> cmd => match cmd { 191 recv(&cmd_recv) -> cmd => match cmd {
178 Ok(cmd) => self.handle_command(cmd), 192 Ok(cmd) => self.handle_command(cmd),
179 Err(RecvError) => { 193 Err(RecvError) => {
180 // Command channel has closed, so shut down 194 // Command channel has closed, so shut down
181 self.running = false; 195 break;
182 }, 196 },
183 }, 197 },
184 recv(self.watcher.message_recv) -> msg => match msg { 198 recv(self.watcher.message_recv) -> msg => match msg {
185 Ok(msg) => self.handle_message(msg, task_send), 199 Ok(msg) => self.handle_message(msg, task_send),
186 Err(RecvError) => {}, 200 Err(RecvError) => {
201 // Task channel has closed, so shut down
202 break;
203 },
187 } 204 }
188 }; 205 };
189 206