pub struct InstanceLock { /* private fields */ }Expand description
A shared or exclusive advisory lock on a file, held for as long as this value lives.
Every running instance of an application holds a shared lock; any number of
them can at once. Something that has to act once they are all gone, such as a service that
cleans up after the last window closes, waits for the exclusive lock
on the same file, and wakes when the last shared lock is released, however that happens: a
normal exit, a crash or a kill -9.
// In every instance, for as long as it runs:
let _instance = InstanceLock::shared(&path)?;
// In the service, on a thread of its own:
let last_closed = InstanceLock::wait_exclusive(&path)?;
// ... clean up after the instances ...
drop(last_closed); // let a new instance startThese locks are flock locks, which belong to an open file rather than to a process: two
locks taken on one path inside one process meet each other exactly as two processes would. A
shared lock and an AppLock are two different questions, so keep them on
two different files.
On every platform other than Unix this framework has no advisory lock, so each call returns an
error of kind io::ErrorKind::Unsupported and never Ok, as
AppLock::acquire does.
Implementations§
Source§impl InstanceLock
impl InstanceLock
Takes a shared lock on path, creating the file when it is not there. Any number of
shared locks can be held at once, so this does not wait for other instances.
It waits only while an exclusive lock is held: a service that is cleaning up after the last instance holds that lock until it is done, and an instance starting meanwhile waits for the cleanup instead of running into it. The parent directory has to exist.
§Errors
Returns the I/O error when the file cannot be opened or locked, and
io::ErrorKind::Unsupported on a platform without an advisory lock.
Sourcepub fn try_exclusive(path: &Path) -> Result<Option<Self>>
pub fn try_exclusive(path: &Path) -> Result<Option<Self>>
Takes the exclusive lock on path when nobody holds a lock on it, or answers None at
once because somebody does. The file is created when it is not there; the parent
directory has to exist.
§Errors
Returns the I/O error when the file cannot be opened or locked, and
io::ErrorKind::Unsupported on a platform without an advisory lock. A lock somebody
else holds is Ok(None), not an error.
Sourcepub fn wait_exclusive(path: &Path) -> Result<Self>
pub fn wait_exclusive(path: &Path) -> Result<Self>
Waits until nobody holds a lock on path, then takes the exclusive lock and returns it.
The file is created when it is not there; the parent directory has to exist.
The thread sleeps in the kernel while it waits and costs no processor time. It wakes when
the last holder’s lock is released, which the kernel also does when a holder’s process
dies. The wait cannot be cancelled, so give it a thread of its own, and hold the lock only
as long as the work that needs it: every shared call waits meanwhile.
When nobody holds the lock this returns at once. A service that should wait again for the next group of instances therefore has to learn in some other way that one has started; calling this again in a loop with nobody running would spin.
A released lock is free in a moment rather than in the same instant: a child process
started between fork and exec holds a copy of every open file for those few
milliseconds (see AppLock::acquire).
§Errors
Returns the I/O error when the file cannot be opened or locked, and
io::ErrorKind::Unsupported on a platform without an advisory lock.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for InstanceLock
impl RefUnwindSafe for InstanceLock
impl Send for InstanceLock
impl Sync for InstanceLock
impl Unpin for InstanceLock
impl UnsafeUnpin for InstanceLock
impl UnwindSafe for InstanceLock
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