1# spin-rs 2 3[](https://crates.io/crates/spin) 4[](https://docs.rs/spin/) 5[](https://travis-ci.org/mvdnes/spin-rs) 6 7Spin-based synchronization primitives. 8 9This crate provides [spin-based](https://en.wikipedia.org/wiki/Spinlock) 10versions of the primitives in `std::sync`. Because synchronization is done 11through spinning, the primitives are suitable for use in `no_std` environments. 12 13Before deciding to use `spin`, we recommend reading 14[this superb blog post](https://matklad.github.io/2020/01/02/spinlocks-considered-harmful.html) 15by [@matklad](https://github.com/matklad/) that discusses the pros and cons of 16spinlocks. If you have access to `std`, it's likely that the primitives in 17`std::sync` will serve you better except in very specific circumstances. 18 19## Features 20 21- `Mutex`, `RwLock`, `Once`, `Lazy` and `Barrier` equivalents 22- Support for `no_std` environments 23- [`lock_api`](https://crates.io/crates/lock_api) compatibility 24- Upgradeable `RwLock` guards 25- Guards can be sent and shared between threads 26- Guard leaking 27- Ticket locks 28- Different strategies for dealing with contention 29 30## Usage 31 32Include the following under the `[dependencies]` section in your `Cargo.toml` file. 33 34```toml 35spin = "x.y" 36``` 37 38## Example 39 40When calling `lock` on a `Mutex` you will get a guard value that provides access 41to the data. When this guard is dropped, the mutex will become available again. 42 43```rust 44extern crate spin; 45use std::{sync::Arc, thread}; 46 47fn main() { 48 let counter = Arc::new(spin::Mutex::new(0)); 49 50 let thread = thread::spawn({ 51 let counter = counter.clone(); 52 move || { 53 for _ in 0..100 { 54 *counter.lock() += 1; 55 } 56 } 57 }); 58 59 for _ in 0..100 { 60 *counter.lock() += 1; 61 } 62 63 thread.join().unwrap(); 64 65 assert_eq!(*counter.lock(), 200); 66} 67``` 68 69## Feature flags 70 71The crate comes with a few feature flags that you may wish to use. 72 73- `mutex` enables the `Mutex` type. 74 75- `spin_mutex` enables the `SpinMutex` type. 76 77- `ticket_mutex` enables the `TicketMutex` type. 78 79- `use_ticket_mutex` switches to a ticket lock for the implementation of `Mutex`. This 80 is recommended only on targets for which ordinary spinning locks perform very badly 81 because it will change the implementation used by other crates that depend on `spin`. 82 83- `rwlock` enables the `RwLock` type. 84 85- `once` enables the `Once` type. 86 87- `lazy` enables the `Lazy` type. 88 89- `barrier` enables the `Barrier` type. 90 91- `lock_api` enables support for [`lock_api`](https://crates.io/crates/lock_api) 92 93- `std` enables support for thread yielding instead of spinning. 94 95- `portable_atomic` enables usage of the `portable-atomic` crate 96 to support platforms without native atomic operations (Cortex-M0, etc.). 97 The `portable_atomic_unsafe_assume_single_core` cfg or `critical-section` feature 98 of `portable-atomic` crate must also be set by the final binary crate. 99 100 When using the cfg, this can be done by adapting the following snippet to the `.cargo/config` file: 101 ``` 102 [target.<target>] 103 rustflags = [ "--cfg", "portable_atomic_unsafe_assume_single_core" ] 104 ``` 105 Note that this cfg is unsafe by nature, and enabling it for multicore systems is unsound. 106 107 When using the `critical-section` feature, you need to implement the critical-section 108 implementation that sound for your system by implementing an unsafe trait. 109 See [the documentation for the `portable-atomic` crate](https://docs.rs/portable-atomic/latest/portable_atomic/#optional-cfg) 110 for more information. 111 112## Remarks 113 114It is often desirable to have a lock shared between threads. Wrapping the lock in an 115`std::sync::Arc` is route through which this might be achieved. 116 117Locks provide zero-overhead access to their data when accessed through a mutable 118reference by using their `get_mut` methods. 119 120The behaviour of these lock is similar to their namesakes in `std::sync`. they 121differ on the following: 122 123- Locks will not be poisoned in case of failure. 124- Threads will not yield to the OS scheduler when encounter a lock that cannot be 125 accessed. Instead, they will 'spin' in a busy loop until the lock becomes available. 126 127Many of the feature flags listed above are enabled by default. If you're writing a 128library, we recommend disabling those that you don't use to avoid increasing compilation 129time for your crate's users. You can do this like so: 130 131``` 132[dependencies] 133spin = { version = "x.y", default-features = false, features = [...] } 134``` 135 136## Minimum Safe Rust Version (MSRV) 137 138This crate is guaranteed to compile on a Minimum Safe Rust Version (MSRV) of 1.38.0 and above. 139This version will not be changed without a minor version bump. 140 141## License 142 143`spin` is distributed under the MIT License, (See `LICENSE`). 144