diff options
Diffstat (limited to 'crates/ra_lsp_server/src/thread_watcher.rs')
-rw-r--r-- | crates/ra_lsp_server/src/thread_watcher.rs | 81 |
1 files changed, 0 insertions, 81 deletions
diff --git a/crates/ra_lsp_server/src/thread_watcher.rs b/crates/ra_lsp_server/src/thread_watcher.rs deleted file mode 100644 index 99825d440..000000000 --- a/crates/ra_lsp_server/src/thread_watcher.rs +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | use std::thread; | ||
2 | |||
3 | use crossbeam_channel::{bounded, unbounded, Receiver, Sender}; | ||
4 | use drop_bomb::DropBomb; | ||
5 | use failure::format_err; | ||
6 | |||
7 | use crate::Result; | ||
8 | |||
9 | pub struct Worker<I, O> { | ||
10 | pub inp: Sender<I>, | ||
11 | pub out: Receiver<O>, | ||
12 | } | ||
13 | |||
14 | impl<I, O> Worker<I, O> { | ||
15 | pub fn spawn<F>(name: &'static str, buf: usize, f: F) -> (Self, ThreadWatcher) | ||
16 | where | ||
17 | F: FnOnce(Receiver<I>, Sender<O>) + Send + 'static, | ||
18 | I: Send + 'static, | ||
19 | O: Send + 'static, | ||
20 | { | ||
21 | let (worker, inp_r, out_s) = worker_chan(buf); | ||
22 | let watcher = ThreadWatcher::spawn(name, move || f(inp_r, out_s)); | ||
23 | (worker, watcher) | ||
24 | } | ||
25 | |||
26 | pub fn stop(self) -> Receiver<O> { | ||
27 | self.out | ||
28 | } | ||
29 | |||
30 | pub fn send(&self, item: I) { | ||
31 | self.inp.send(item) | ||
32 | } | ||
33 | } | ||
34 | |||
35 | pub struct ThreadWatcher { | ||
36 | name: &'static str, | ||
37 | thread: thread::JoinHandle<()>, | ||
38 | bomb: DropBomb, | ||
39 | } | ||
40 | |||
41 | impl ThreadWatcher { | ||
42 | fn spawn(name: &'static str, f: impl FnOnce() + Send + 'static) -> ThreadWatcher { | ||
43 | let thread = thread::spawn(f); | ||
44 | ThreadWatcher { | ||
45 | name, | ||
46 | thread, | ||
47 | bomb: DropBomb::new(format!("ThreadWatcher {} was not stopped", name)), | ||
48 | } | ||
49 | } | ||
50 | |||
51 | pub fn stop(mut self) -> Result<()> { | ||
52 | log::info!("waiting for {} to finish ...", self.name); | ||
53 | let name = self.name; | ||
54 | self.bomb.defuse(); | ||
55 | let res = self | ||
56 | .thread | ||
57 | .join() | ||
58 | .map_err(|_| format_err!("ThreadWatcher {} died", name)); | ||
59 | match &res { | ||
60 | Ok(()) => log::info!("... {} terminated with ok", name), | ||
61 | Err(_) => log::error!("... {} terminated with err", name), | ||
62 | } | ||
63 | res | ||
64 | } | ||
65 | } | ||
66 | |||
67 | /// Sets up worker channels in a deadlock-avoind way. | ||
68 | /// If one sets both input and output buffers to a fixed size, | ||
69 | /// a worker might get stuck. | ||
70 | fn worker_chan<I, O>(buf: usize) -> (Worker<I, O>, Receiver<I>, Sender<O>) { | ||
71 | let (input_sender, input_receiver) = bounded::<I>(buf); | ||
72 | let (output_sender, output_receiver) = unbounded::<O>(); | ||
73 | ( | ||
74 | Worker { | ||
75 | inp: input_sender, | ||
76 | out: output_receiver, | ||
77 | }, | ||
78 | input_receiver, | ||
79 | output_sender, | ||
80 | ) | ||
81 | } | ||