aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-08-30 18:23:28 +0100
committerAleksey Kladov <[email protected]>2019-08-30 18:32:59 +0100
commit983de30a567f2cb4d9e28e12702e509ca713da62 (patch)
tree9bdd597701e1b150492a78b6c85ff856f0fc51bd /crates/ra_lsp_server
parent7cc14a759699dd2503199116521e9ba65e3f1aa8 (diff)
inline thread-worker
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r--crates/ra_lsp_server/Cargo.toml4
-rw-r--r--crates/ra_lsp_server/src/lib.rs1
-rw-r--r--crates/ra_lsp_server/src/project_model.rs4
-rw-r--r--crates/ra_lsp_server/src/thread_worker.rs49
4 files changed, 52 insertions, 6 deletions
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index 4f834519c..eb4812633 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -15,9 +15,8 @@ log = "0.4.3"
15lsp-types = { version = "0.60.0", features = ["proposed"] } 15lsp-types = { version = "0.60.0", features = ["proposed"] }
16rustc-hash = "1.0" 16rustc-hash = "1.0"
17parking_lot = "0.9.0" 17parking_lot = "0.9.0"
18 18jod-thread = "0.1.0"
19ra_vfs = "0.3.0" 19ra_vfs = "0.3.0"
20thread_worker = { path = "../thread_worker" }
21ra_syntax = { path = "../ra_syntax" } 20ra_syntax = { path = "../ra_syntax" }
22ra_text_edit = { path = "../ra_text_edit" } 21ra_text_edit = { path = "../ra_text_edit" }
23ra_ide_api = { path = "../ra_ide_api" } 22ra_ide_api = { path = "../ra_ide_api" }
@@ -27,7 +26,6 @@ ra_prof = { path = "../ra_prof" }
27ra_vfs_glob = { path = "../ra_vfs_glob" } 26ra_vfs_glob = { path = "../ra_vfs_glob" }
28 27
29[dev-dependencies] 28[dev-dependencies]
30jod-thread = "0.1.0"
31tempfile = "3" 29tempfile = "3"
32test_utils = { path = "../test_utils" } 30test_utils = { path = "../test_utils" }
33 31
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs
index 2c5d7c72d..69a577b3e 100644
--- a/crates/ra_lsp_server/src/lib.rs
+++ b/crates/ra_lsp_server/src/lib.rs
@@ -8,6 +8,7 @@ mod project_model;
8pub mod req; 8pub mod req;
9pub mod config; 9pub mod config;
10mod world; 10mod world;
11mod thread_worker;
11 12
12pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>; 13pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
13pub use crate::{ 14pub use crate::{
diff --git a/crates/ra_lsp_server/src/project_model.rs b/crates/ra_lsp_server/src/project_model.rs
index ad59cde64..6234563f2 100644
--- a/crates/ra_lsp_server/src/project_model.rs
+++ b/crates/ra_lsp_server/src/project_model.rs
@@ -1,8 +1,6 @@
1use std::path::PathBuf; 1use std::path::PathBuf;
2 2
3use thread_worker::Worker; 3use crate::{thread_worker::Worker, Result};
4
5use crate::Result;
6 4
7pub use ra_project_model::{ 5pub use ra_project_model::{
8 CargoWorkspace, Package, ProjectWorkspace, Sysroot, Target, TargetKind, 6 CargoWorkspace, Package, ProjectWorkspace, Sysroot, Target, TargetKind,
diff --git a/crates/ra_lsp_server/src/thread_worker.rs b/crates/ra_lsp_server/src/thread_worker.rs
new file mode 100644
index 000000000..68e5c124d
--- /dev/null
+++ b/crates/ra_lsp_server/src/thread_worker.rs
@@ -0,0 +1,49 @@
1//! Small utility to correctly spawn crossbeam-channel based worker threads.
2
3use crossbeam_channel::{bounded, unbounded, Receiver, Sender};
4
5/// A wrapper around event-processing thread with automatic shutdown semantics.
6pub struct Worker<I, O> {
7 // XXX: field order is significant here.
8 //
9 // In Rust, fields are dropped in the declaration order, and we rely on this
10 // here. We must close input first, so that the `thread` (who holds the
11 // opposite side of the channel) noticed shutdown. Then, we must join the
12 // thread, but we must keep out alive so that the thread does not panic.
13 //
14 // Note that a potential problem here is that we might drop some messages
15 // from receiver on the floor. This is ok for rust-analyzer: we have only a
16 // single client, so, if we are shutting down, nobody is interested in the
17 // unfinished work anyway!
18 sender: Sender<I>,
19 _thread: jod_thread::JoinHandle<()>,
20 receiver: Receiver<O>,
21}
22
23impl<I, O> Worker<I, O> {
24 pub fn spawn<F>(name: &'static str, buf: usize, f: F) -> Worker<I, O>
25 where
26 F: FnOnce(Receiver<I>, Sender<O>) + Send + 'static,
27 I: Send + 'static,
28 O: Send + 'static,
29 {
30 // Set up worker channels in a deadlock-avoiding way. If one sets both input
31 // and output buffers to a fixed size, a worker might get stuck.
32 let (sender, input_receiver) = bounded::<I>(buf);
33 let (output_sender, receiver) = unbounded::<O>();
34 let _thread = jod_thread::Builder::new()
35 .name(name.to_string())
36 .spawn(move || f(input_receiver, output_sender))
37 .expect("failed to spawn a thread");
38 Worker { sender, _thread, receiver }
39 }
40}
41
42impl<I, O> Worker<I, O> {
43 pub fn sender(&self) -> &Sender<I> {
44 &self.sender
45 }
46 pub fn receiver(&self) -> &Receiver<O> {
47 &self.receiver
48 }
49}