Part 1 fixes: complete stdout writes, buffered stdin, Rust type names in schemas, enum variant docs, -32603 for serde errors in handlers, crate docs and modules. End-to-end check of a generated consumer through a fake core.
66 lines
1.7 KiB
Rust
66 lines
1.7 KiB
Rust
//! Advisory lock acquisition and guard lifetime.
|
|
use super::*;
|
|
/// An advisory lock acquisition.
|
|
pub struct Lock {
|
|
path: String,
|
|
wait: bool,
|
|
}
|
|
/// Acquire an advisory lock on a path.
|
|
pub fn lock(path: impl AsRef<Path>) -> Lock {
|
|
Lock {
|
|
path: path.as_ref().to_string_lossy().into_owned(),
|
|
wait: true,
|
|
}
|
|
}
|
|
impl Lock {
|
|
/// Return immediately, without waiting for a held lock.
|
|
pub fn try_now(mut self) -> Self {
|
|
self.wait = false;
|
|
self
|
|
}
|
|
}
|
|
/// Releases its lock on drop, unless kept until process exit.
|
|
pub struct Guard {
|
|
path: Option<String>,
|
|
}
|
|
impl Guard {
|
|
/// Hold this lock until process exit.
|
|
pub fn keep(mut self) {
|
|
self.path.take();
|
|
}
|
|
/// Report whether this guard holds the lock.
|
|
pub fn held(&self) -> bool {
|
|
self.path.is_some()
|
|
}
|
|
}
|
|
impl Drop for Guard {
|
|
fn drop(&mut self) {
|
|
if let Some(path) = self.path.take() {
|
|
let _ = notify("core.unlock", json!({"path":path}));
|
|
}
|
|
}
|
|
}
|
|
impl IntoFuture for Lock {
|
|
type Output = Result<Guard>;
|
|
type IntoFuture = LocalBoxFuture<'static, Self::Output>;
|
|
fn into_future(self) -> Self::IntoFuture {
|
|
Box::pin(async move {
|
|
let lease = std::rc::Rc::new(Lease {
|
|
path: self.path.clone(),
|
|
held: std::cell::Cell::new(false),
|
|
});
|
|
let mut c = call("core.lock", json!({"path":self.path,"wait":self.wait}));
|
|
c.unlock = Some(lease.clone());
|
|
let result = c.await?;
|
|
lease.held.set(false);
|
|
Ok(Guard {
|
|
path: if result["held"] == true {
|
|
Some(self.path)
|
|
} else {
|
|
None
|
|
},
|
|
})
|
|
})
|
|
}
|
|
}
|