Skip to main content

InstanceLock

Struct InstanceLock 

Source
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 start

These 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

Source

pub fn shared(path: &Path) -> Result<Self>

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.

Source

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.

Source

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§

Source§

impl Debug for InstanceLock

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.