diff options
Diffstat (limited to 'third_party/rust/jobserver/src/wasm.rs')
-rw-r--r-- | third_party/rust/jobserver/src/wasm.rs | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/third_party/rust/jobserver/src/wasm.rs b/third_party/rust/jobserver/src/wasm.rs new file mode 100644 index 0000000000..3793bd67cc --- /dev/null +++ b/third_party/rust/jobserver/src/wasm.rs @@ -0,0 +1,95 @@ +use std::io; +use std::process::Command; +use std::sync::{Arc, Condvar, Mutex}; +use std::thread::{Builder, JoinHandle}; + +#[derive(Debug)] +pub struct Client { + inner: Arc<Inner>, +} + +#[derive(Debug)] +struct Inner { + count: Mutex<usize>, + cvar: Condvar, +} + +#[derive(Debug)] +pub struct Acquired(()); + +impl Client { + pub fn new(limit: usize) -> io::Result<Client> { + Ok(Client { + inner: Arc::new(Inner { + count: Mutex::new(limit), + cvar: Condvar::new(), + }), + }) + } + + pub unsafe fn open(_s: &str) -> Option<Client> { + None + } + + pub fn acquire(&self) -> io::Result<Acquired> { + let mut lock = self.inner.count.lock().unwrap_or_else(|e| e.into_inner()); + while *lock == 0 { + lock = self + .inner + .cvar + .wait(lock) + .unwrap_or_else(|e| e.into_inner()); + } + *lock -= 1; + Ok(Acquired(())) + } + + pub fn release(&self, _data: Option<&Acquired>) -> io::Result<()> { + let mut lock = self.inner.count.lock().unwrap_or_else(|e| e.into_inner()); + *lock += 1; + drop(lock); + self.inner.cvar.notify_one(); + Ok(()) + } + + pub fn string_arg(&self) -> String { + panic!( + "On this platform there is no cross process jobserver support, + so Client::configure is not supported." + ); + } + + pub fn available(&self) -> io::Result<usize> { + let lock = self.inner.count.lock().unwrap_or_else(|e| e.into_inner()); + Ok(*lock) + } + + pub fn configure(&self, _cmd: &mut Command) { + unreachable!(); + } +} + +#[derive(Debug)] +pub struct Helper { + thread: JoinHandle<()>, +} + +pub(crate) fn spawn_helper( + client: crate::Client, + state: Arc<super::HelperState>, + mut f: Box<dyn FnMut(io::Result<crate::Acquired>) + Send>, +) -> io::Result<Helper> { + let thread = Builder::new().spawn(move || { + state.for_each_request(|_| f(client.acquire())); + })?; + + Ok(Helper { thread: thread }) +} + +impl Helper { + pub fn join(self) { + // TODO: this is not correct if the thread is blocked in + // `client.acquire()`. + drop(self.thread.join()); + } +} |