pub struct AppLock { /* private fields */ }Expand description
An advisory lock on a file, held by the running process for as long as this value lives.
The lock is the operating system’s, not the file’s existence: the kernel releases it when the process ends, so a crash or a power cut never leaves a lock behind. Dropping the value releases it too.
The file itself holds the process id of the holder as text, and that is only ever material
for a message to the user: a process id is reused, so nothing may be decided from it. The
decision is AppLock::acquire’s answer and nothing else.
let dir = data_dir("qfocus").expect("a home directory");
std::fs::create_dir_all(&dir)?;
match AppLock::acquire(&dir.join("lock"))? {
Some(_lock) => { /* this instance may write; the lock lives as long as `_lock` */ }
None => { /* another instance is running */ }
}Implementations§
Source§impl AppLock
impl AppLock
Sourcepub fn acquire(path: &Path) -> Result<Option<Self>>
pub fn acquire(path: &Path) -> Result<Option<Self>>
Takes the lock on path, creating the file when it is not there, or answers None
because another process holds it.
The parent directory has to exist. On success the process id of this process is written
into the file, for a message that names the holder; see holder_pid.
On Unix systems this is flock(LOCK_EX | LOCK_NB), which the kernel releases when the
process dies. Locks of this kind are per open file, not per process, so a second
acquire on the same path inside one process answers None as well.
A child process started between the moment the lock is taken and the moment it is released
keeps it for a few milliseconds longer: between fork and exec the child holds a copy of
every open file, this file among them, and the kernel counts the lock as held until that copy
is closed. So a released lock is free in a moment, not in the same instant, and a program
that starts children may need to wait briefly before it can take its own lock again.
On every other platform, Windows among them, this framework has no advisory lock yet:
acquire returns an error of kind io::ErrorKind::Unsupported and never Ok, so an
application is told it has no lock instead of quietly running without one. Windows would
need LockFileEx, which is not reachable without unsafe, and this framework forbids
unsafe.
§Errors
Returns the I/O error when the file cannot be opened or written, and
io::ErrorKind::Unsupported on a platform without an advisory lock. A lock another
process holds is Ok(None), not an error.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for AppLock
impl RefUnwindSafe for AppLock
impl Send for AppLock
impl Sync for AppLock
impl Unpin for AppLock
impl UnsafeUnpin for AppLock
impl UnwindSafe for AppLock
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more