{"id":20569626,"url":"https://github.com/pedromfedricci/mcslock","last_synced_at":"2025-04-14T16:35:37.974Z","repository":{"id":206128793,"uuid":"713188650","full_name":"pedromfedricci/mcslock","owner":"pedromfedricci","description":"An implementation of Mellor-Crummey and Scott lock for mutual exclusion, referred to as MCS lock.","archived":false,"fork":false,"pushed_at":"2024-10-30T00:42:51.000Z","size":417,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-30T02:52:44.661Z","etag":null,"topics":["concurrency","multithreading","mutex","mutual-exclusion","rust-lang","spinlock","synchronization"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/mcslock","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pedromfedricci.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-11-02T02:27:52.000Z","updated_at":"2024-09-23T12:23:40.000Z","dependencies_parsed_at":"2024-01-04T02:14:48.793Z","dependency_job_id":"8502fbde-7ad7-49c7-abc4-f83cf60dbb8a","html_url":"https://github.com/pedromfedricci/mcslock","commit_stats":null,"previous_names":["pedromfedricci/mcslock"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedromfedricci%2Fmcslock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedromfedricci%2Fmcslock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedromfedricci%2Fmcslock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedromfedricci%2Fmcslock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pedromfedricci","download_url":"https://codeload.github.com/pedromfedricci/mcslock/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248917231,"owners_count":21182956,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["concurrency","multithreading","mutex","mutual-exclusion","rust-lang","spinlock","synchronization"],"created_at":"2024-11-16T05:09:02.134Z","updated_at":"2025-04-14T16:35:37.966Z","avatar_url":"https://github.com/pedromfedricci.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# A simple and correct implementation of the MCS lock\n\n[![MIT][mit-badge]][mit]\n[![Apache 2.0][apache2-badge]][apache2]\n[![Crates][crates-badge]][crates]\n[![Docs][docs-badge]][docs]\n[![CI][ci-badge]][ci]\n[![Codecov][codecov-badge]][codecov]\n![No_std][no_std-badge]\n\nMCS lock is a List-Based Queuing Lock that avoids network contention by having\nthreads spin on local memory locations. The main properties of this mechanism are:\n\n- guarantees FIFO ordering of lock acquisitions;\n- spins on locally-accessible flag variables only;\n- requires a small constant amount of space per lock; and\n- works equally well (requiring only O(1) network transactions per lock\n  acquisition) on machines with and without coherent caches.\n\nThis algorithm and several others were introduced by [Mellor-Crummey and Scott]\npaper. And a simpler correctness proof of the MCS lock was proposed by\n[Johnson and Harathi].\n\n## Spinlock use cases\n\nIt is noteworthy to mention that [spinlocks are usually not what you want]. The\nmajority of use cases are well covered by OS-based mutexes like [`std::sync::Mutex`]\nand [`parking_lot::Mutex`]. These implementations will notify the system that the\nwaiting thread should be parked, freeing the processor to work on something else.\n\nSpinlocks are only efficient in very few circumstances where the overhead\nof context switching or process rescheduling are greater than busy waiting\nfor very short periods. Spinlocks can be useful inside operating-system kernels,\non embedded systems or even complement other locking designs. As a reference\nuse case, some [Linux kernel mutexes] run an customized MCS lock specifically\ntailored for optimistic spinning during contention before actually sleeping.\nThis implementation is `no_std` by default, so it's useful in those environments.\n\n## Install\n\nRun the following Cargo command in your project directory:\n\n```bash\ncargo add mcslock\n```\n\nOr add a entry under the `[dependencies]` section in your `Cargo.toml`:\n\n```toml\n# Cargo.toml\n\n[dependencies]\n# Features: `yield`, `barging`, `thread_local` and `lock_api`.\nmcslock = { version = \"0.4\", features = [\"thread_local\"] }\n```\n\n## Documentation\n\nThis project documentation is hosted at [docs.rs][docs]. Or you can build it\nlocally with the following command:\n\n```bash\nRUSTDOCFLAGS=\"--cfg docsrs\" cargo +nightly doc --all-features --open\n```\n\n## Locking with a raw MCS spinlock\n\nThis implementation operates under FIFO. Raw locking APIs require exclusive\naccess to a locally accessible queue node. This node is represented by the\n[`raw::MutexNode`] type. Callers are responsible for instantiating the queue\nnodes themselves. This implementation is `no_std` compatible. See the [`raw`]\nmodule for more information.\n\n```rust\nuse std::sync::Arc;\nuse std::thread;\n\n// Simply spins during contention.\nuse mcslock::raw::{spins::Mutex, MutexNode};\n\nfn main() {\n    let mutex = Arc::new(Mutex::new(0));\n    let c_mutex = Arc::clone(\u0026mutex);\n\n    thread::spawn(move || {\n        // A queue node must be mutably accessible.\n        // Critical section must be defined as a closure.\n        let mut node = MutexNode::new();\n        c_mutex.lock_with_then(\u0026mut node, |data| *data = 10);\n    })\n    .join().expect(\"thread::spawn failed\");\n\n    // A node may also be transparently allocated in the stack.\n    // Critical section must be defined as a closure.\n    assert_eq!(mutex.try_lock_then(|data| *data.unwrap()), 10);\n}\n```\n\n## Thread local queue nodes\n\n[`raw::Mutex`] supports locking APIs that access queue nodes that are stored in\nthe thread local storage. These locking APIs require a static reference to a\n[`raw::LocalMutexNode`] key. Keys must be generated by the [`thread_local_node!`]\nmacro. Thread local nodes are not `no_std` compatible and can be enabled through\nthe `thread_local` feature.\n\n```rust\nuse std::sync::Arc;\nuse std::thread;\n\n// Simply spins during contention.\nuse mcslock::raw::spins::Mutex;\n\n// Requires `thread_local` feature.\nmcslock::thread_local_node!(static NODE);\n\nfn main() {\n    let mutex = Arc::new(Mutex::new(0));\n    let c_mutex = Arc::clone(\u0026mutex);\n\n    thread::spawn(move || {\n        // Local node handles are provided by reference.\n        // Critical section must be defined as a closure.\n        c_mutex.lock_with_local_then(\u0026NODE, |data| *data = 10);\n    })\n    .join().expect(\"thread::spawn failed\");\n\n    // A node may also be transparently allocated in the stack.\n    // Critical section must be defined as a closure.\n    assert_eq!(mutex.try_lock_then(|data| *data.unwrap()), 10);\n}\n```\n\n## Locking with a barging MCS spinlock\n\nThis implementation will have non-waiting threads race for the lock against\nthe front of the waiting queue thread, which means this it is an unfair lock.\nThis implementation is suitable for `no_std` environments, and the locking\nAPIs are compatible with the [lock_api] crate. See [`barging`] and\n[`barging::lock_api`] modules for more information.\n\n```rust\nuse std::sync::Arc;\nuse std::thread;\n\n// Requires `barging` feature.\n// Spins with exponential backoff during contention.\nuse mcslock::barging::spins::backoff::Mutex;\n\nfn main() {\n    let mutex = Arc::new(Mutex::new(0));\n    let c_mutex = Arc::clone(\u0026mutex);\n\n    thread::spawn(move || {\n        *c_mutex.try_lock().unwrap() = 10;\n    })\n    .join().expect(\"thread::spawn failed\");\n\n    assert_eq!(*mutex.lock(), 10);\n}\n```\n\n## Features\n\nThis crate dos not provide any default features. Features that can be enabled\nare:\n\n### yield\n\nThe `yield` feature requires linking to the standard library, so it is not\nsuitable for `no_std` environments. By enabling the `yield` feature, instead\nof busy-waiting during lock acquisitions and releases, this will call\n[`std::thread::yield_now`], which cooperatively gives up a timeslice to the\nOS scheduler. This may cause a context switch, so you may not want to enable\nthis feature if your intention is to to actually do optimistic spinning. The\ndefault implementation calls [`core::hint::spin_loop`], which does in fact\njust simply busy-waits. This feature is not `no_std` compatible.\n\n### thread_local\n\nThe `thread_local` feature enables [`raw::Mutex`] locking APIs that operate over\nqueue nodes that are stored at the thread local storage. These locking APIs\nrequire a static reference to [`raw::LocalMutexNode`] keys. Keys must be generated\nby the [`thread_local_node!`] macro. This feature also enables memory optimizations\nfor [`barging::Mutex`] locking operations. This feature is not `no_std`\ncompatible.\n\n### barging\n\nThe `barging` feature provides locking APIs that are compatible with the\n[lock_api] crate. It does not require node allocations from the caller.\nThe [`barging`] module is suitable for `no_std` environments. This implementation\nis not fair (does not guarantee FIFO), but can improve throughput when the lock\nis heavily contended.\n\n### lock_api\n\nThis feature implements the [`RawMutex`] trait from the [lock_api] crate for\n[`barging::Mutex`]. Aliases are provided by the [`barging::lock_api`] (`no_std`)\nmodule.\n\n## Minimum Supported Rust Version (MSRV)\n\nThis crate is guaranteed to compile on a Minimum Supported Rust Version (MSRV)\nof 1.65.0 and above. This version will not be changed without a minor version\nbump. If you intend to use this crate but can only target a older Rust version,\nfeel free to open a issue with your specific target, it is possible to lower\nthis crate MSRV substantially, it just has not been explored yet.\n\n## Related projects\n\nThese projects provide MCS lock implementations with different APIs, capabilities,\nimplementation details or compiler requirements, you can check their repositories:\n\n- mcs-rs: \u003chttps://github.com/gereeter/mcs-rs\u003e\n- libmcs: \u003chttps://github.com/topecongiro/libmcs\u003e\n\n## License\n\nLicensed under either of\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or \u003chttp://apache.org/licenses/LICENSE-2.0\u003e)\n- MIT license ([LICENSE-MIT](LICENSE-MIT) or \u003chttp://opensource.org/licenses/MIT\u003e)\n\n## Contributing\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you, as defined in the Apache-2.0 license, shall\nbe dual licensed as above, without any additional terms or conditions.\n\n## Code review\n\nIt is recommended to always use [cargo-crev] to verify the trustworthiness of\neach of your dependencies, including this one.\n\n[mit-badge]: https://img.shields.io/badge/License-MIT-blue.svg\n[apache2-badge]: https://img.shields.io/badge/License-Apache_2.0-yellow.svg\n[docs-badge]: https://img.shields.io/docsrs/mcslock\n[crates-badge]: https://img.shields.io/crates/v/mcslock\n[ci-badge]: https://github.com/pedromfedricci/mcslock/actions/workflows/ci.yml/badge.svg\n[codecov-badge]: https://codecov.io/gh/pedromfedricci/mcslock/graph/badge.svg?token=A54PAF1K74\n[no_std-badge]: https://img.shields.io/badge/no__std-compatible-success.svg\n\n[mit]: https://opensource.org/licenses/MIT\n[apache2]: https://opensource.org/licenses/Apache-2.0\n[docs]: https://docs.rs/mcslock\n[crates]: https://crates.io/crates/mcslock\n[ci]: https://github.com/pedromfedricci/mcslock/actions/workflows/ci.yml\n[codecov]: https://codecov.io/gh/pedromfedricci/mcslock\n[cargo-crev]: https://github.com/crev-dev/cargo-crev\n\n[Mellor-Crummey and Scott]: https://www.cs.rochester.edu/~scott/papers/1991_TOCS_synch.pdf\n[Johnson and Harathi]: https://web.archive.org/web/20140411142823/http://www.cise.ufl.edu/tr/DOC/REP-1992-71.pdf\n[spinlocks are usually not what you want]: https://matklad.github.io/2020/01/02/spinlocks-considered-harmful.html\n[Linux kernel mutexes]: https://www.kernel.org/doc/html/latest/locking/mutex-design.html\n\n[`raw`]: https://docs.rs/mcslock/latest/mcslock/raw/index.html\n[`raw::Mutex`]: https://docs.rs/mcslock/latest/mcslock/raw/struct.Mutex.html\n[`raw::MutexNode`]: https://docs.rs/mcslock/latest/mcslock/raw/struct.MutexNode.html\n[`raw::LocalMutexNode`]: https://docs.rs/mcslock/latest/mcslock/raw/struct.LocalMutexNode.html\n[`barging`]: https://docs.rs/mcslock/latest/mcslock/barging/index.html\n[`barging::lock_api`]: https://docs.rs/mcslock/latest/mcslock/barging/lock_api/index.html\n[`barging::Mutex`]: https://docs.rs/mcslock/latest/mcslock/barging/struct.Mutex.html\n[`thread_local_node!`]: https://docs.rs/mcslock/latest/mcslock/macro.thread_local_node.html\n\n[`std::sync::Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html\n[`std::thread::yield_now`]: https://doc.rust-lang.org/std/thread/fn.yield_now.html\n[`core::hint::spin_loop`]: https://doc.rust-lang.org/core/hint/fn.spin_loop.html\n\n[lock_api]: https://docs.rs/lock_api/latest/lock_api\n[`RawMutex`]: https://docs.rs/lock_api/latest/lock_api/trait.RawMutex.html\n[`RawMutexFair`]: https://docs.rs/lock_api/latest/lock_api/trait.RawMutexFair.html\n[`parking_lot::Mutex`]: https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedromfedricci%2Fmcslock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpedromfedricci%2Fmcslock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedromfedricci%2Fmcslock/lists"}