#raii #flock #mutex #file-lock

fmutex

Cross-platform mutual exclusion across processes on a file or path

4 releases (2 breaking)

0.3.0 May 22, 2025
0.2.1 Mar 10, 2025
0.2.0 Mar 8, 2025
0.1.0 Feb 9, 2022

#364 in Filesystem

Download history 322/week @ 2025-07-30 266/week @ 2025-08-06 231/week @ 2025-08-13 698/week @ 2025-08-20 446/week @ 2025-08-27 1005/week @ 2025-09-03 951/week @ 2025-09-10 975/week @ 2025-09-17 456/week @ 2025-09-24 452/week @ 2025-10-01 490/week @ 2025-10-08 658/week @ 2025-10-15 653/week @ 2025-10-22 657/week @ 2025-10-29 358/week @ 2025-11-05 1077/week @ 2025-11-12

2,860 downloads per month
Used in 3 crates

MIT/Apache

27KB
302 lines

fmutex

Crates.io Version Docs.rs Latest Build Status

Mutual exclusion across processes on a file descriptor or path.

  • On Unix-like systems this is implemented use flock(2).
  • On Windows this is implemented using LockFileEx.

🚀 Getting started

First add fmutex to your Cargo manifest.

cargo add fmutex

Now use one of the provided functions to lock a file descriptor (Unix) or handle (Windows) or a file path.

For exclusive locks (only one process can hold the lock):

For shared locks (multiple processes can hold the lock simultaneously, but not when an exclusive lock is held):

🤸 Usage

lock_exclusive()

let fd = fs::OpenOptions::new().create(true).write(true).open(&path)?;

{
    let _guard = fmutex::lock_exclusive(&fd)?;

    // do mutually exclusive stuff here

} // <-- `_guard` dropped here and the lock is released

try_lock_exclusive()

let fd = fs::OpenOptions::new().create(true).write(true).open(&path)?;

match fmutex::try_lock_exclusive(&fd)? {
    Some(_guard) => {

        // do mutually exclusive stuff here

    } // <-- `_guard` dropped here and the lock is released

    None => {
        eprintln!("the lock could not be acquired!");
    }
}

lock_exclusive_path()

let path = "path/to/my/file.txt";

{
    let _guard = fmutex::lock_exclusive_path(path)?;

    // do mutually exclusive stuff here

} // <-- `_guard` dropped here and the lock is released

try_lock_exclusive_path()

let path = "path/to/my/file.txt";

match fmutex::try_lock_exclusive_path(path)? {
    Some(_guard) => {

        // do mutually exclusive stuff here

    } // <-- `_guard` dropped here and the lock is released

    None => {
        eprintln!("the lock could not be acquired!");
    }
}

lock_shared()

let fd = fs::OpenOptions::new().create(true).write(true).open(&path)?;

{
    let _guard = fmutex::lock_shared(&fd)?;

    // do shared read-only operations here
    // other processes can also acquire shared locks simultaneously

} // <-- `_guard` dropped here and the lock is released

try_lock_shared()

let fd = fs::OpenOptions::new().create(true).write(true).open(&path)?;

match fmutex::try_lock_shared(&fd)? {
    Some(_guard) => {

        // do shared read-only operations here
        // other processes can also acquire shared locks simultaneously

    } // <-- `_guard` dropped here and the lock is released

    None => {
        eprintln!("the shared lock could not be acquired (file is exclusively locked)!");
    }
}

lock_shared_path()

let path = "path/to/my/file.txt";

{
    let _guard = fmutex::lock_shared_path(path)?;

    // do shared read-only operations here
    // other processes can also acquire shared locks simultaneously

} // <-- `_guard` dropped here and the lock is released

try_lock_shared_path()

let path = "path/to/my/file.txt";

match fmutex::try_lock_shared_path(path)? {
    Some(_guard) => {

        // do shared read-only operations here
        // other processes can also acquire shared locks simultaneously

    } // <-- `_guard` dropped here and the lock is released

    None => {
        eprintln!("the shared lock could not be acquired (file is exclusively locked)!");
    }
}

License

This project is distributed under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-APACHE and LICENSE-MIT for details.

Dependencies

~0–11MB
~78K SLoC