#![feature(negative_impls)]
#![allow(clippy::comparison_chain)]
#![allow(unused, dead_code)]
mod non_thread_local {
use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
use core::sync::atomic::{spin_loop_hint as spin_loop, AtomicU8, AtomicUsize, Ordering::SeqCst};
use std::io::{self, BufRead, Read, Seek, SeekFrom, Write};
use std::sync::{
LockResult, PoisonError,
TryLockError::{Poisoned, WouldBlock},
TryLockResult,
};
use std::thread::panicking;
use std::sync::atomic::Ordering::Relaxed;
use thread_local::ThreadLocal;
// sentinel most significant bit,write lock
const WRITE: usize = usize::MAX - (usize::MAX / 2);
// sentinel pen-most significant bit,poisoned state
const POISON: usize = WRITE / 2;
const LOCK: u8 = 2;
const POISON_M: u8 = 1;
/// An allocation-free [`Mutex`][`std::sync::Mutex`] made in pure Rust.
pub struct Mutex<T> {
value: UnsafeCell<T>,
ref_count: AtomicU8,
}
unsafe impl<T: Send> Send for Mutex<T> {}
unsafe impl<T: Send> Sync for Mutex<T> {}
impl<T> Mutex<T> {
/// Creates a new mutex in an unlocked state ready for use.
///
/// This function it's constant only without `debug_assertions` due to declare a thread local
/// storage to avoid acquire the lock twice from the same thread.
#[inline]
pub const fn new(x: T) -> Self {
Self {
value: UnsafeCell::new(x),
ref_count: AtomicU8::new(0),
}
}
/// Acquires a mutex, blocking the current thread until it is able to do so.
///
/// This function will block the local thread until it is available to acquire
/// the mutex. Upon returning, the thread is the only thread with the lock
/// held. An RAII guard is returned to allow scoped unlock of the lock. When
/// the guard goes out of scope, the mutex will be unlocked.
///
/// The exact behavior on locking a mutex in the thread which already holds
/// the lock is left unspecified. However, this function will not return on
/// the second call (it might panic or deadlock, for example).
///
/// # Errors
///
/// If another user of this mutex panicked while holding the mutex, then
/// this call will return an error once the mutex is acquired.
///
/// # Panics
///
/// This function might panic when called if the lock is already held by
/// the current thread only with `debug_assertions`.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use sync_2::Mutex;
/// use std::thread;
///
/// let mutex = Arc::new(Mutex::new(0));
/// let c_mutex = mutex.clone();
///
/// thread::spawn(move || {
/// *c_mutex.lock().unwrap() = 10;
/// }).join().expect("thread::spawn failed");
/// assert_eq!(*mutex.lock().unwrap(), 10);
/// ```
#[inline]
pub fn lock(&self) -> LockResult<MutexGuard<'_, T>> {
loop {
match self.try_lock() {
Ok(e) => break Ok(e),
Err(WouldBlock) => spin_loop(),
Err(Poisoned(e)) => break Err(e),
}
}
}
/// Attempts to acquire this lock.
///
/// If the lock could not be acquired at this time, then [`Err`] is returned.
/// Otherwise, an RAII guard is returned. The lock will be unlocked when the
/// guard is dropped.
///
/// This function does not block.
///
/// # Errors
///
/// If another user of this mutex panicked while holding the mutex, then
/// this call will return failure if the mutex would otherwise be
/// acquired.
///
/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use sync_2::Mutex;
/// use std::thread;
///
/// let mutex = Arc::new(Mutex::new(0));
/// let c_mutex = mutex.clone();
///
/// thread::spawn(move || {
/// let mut lock = c_mutex.try_lock();
/// if let Ok(ref mut mutex) = lock {
/// **mutex = 10;
/// } else {
/// println!("try_lock failed");
/// }
/// }).join().expect("thread::spawn failed");
/// assert_eq!(*mutex.lock().unwrap(), 10);
/// ```
pub fn try_lock(&self) -> TryLockResult<MutexGuard<'_, T>> {
let x = match self.ref_count.fetch_update(
SeqCst,
SeqCst,
|x| if x < LOCK { Some(x | LOCK) } else { None },
) {
Ok(x) => x,
Err(_) => return Err(WouldBlock),
};
if x < POISON_M {
Ok(MutexGuard { lock: self })
} else {
Err(Poisoned(PoisonError::new(MutexGuard { lock: self })))
}
}
/// Determines whether the mutex is poisoned.
///
/// If another thread is active, the mutex can still become poisoned at any
/// time. You should not trust a `false` value for program correctness
/// without additional synchronization.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use sync_2::Mutex;
/// use std::thread;
///
/// let mutex = Arc::new(Mutex::new(0));
/// let c_mutex = mutex.clone();
///
/// let _ = thread::spawn(move || {
/// let _lock = c_mutex.lock().unwrap();
/// panic!(); // the mutex gets poisoned
/// }).join();
/// assert_eq!(mutex.is_poisoned(), true);
/// ```
#[inline]
pub fn is_poisoned(&self) -> bool {
(self.ref_count.load(SeqCst) & POISON_M) == POISON_M
}
/// Returns a mutable reference to the underlying data.
///
/// Since this call borrows the `Mutex` mutably, no actual locking needs to
/// take place -- the mutable borrow statically guarantees no locks exist.
///
/// # Errors
///
/// If another user of this mutex panicked while holding the mutex, then
/// this call will return an error instead.
///
/// # Examples
///
/// ```
/// use sync_2::Mutex;
///
/// let mut mutex = Mutex::new(0);
/// *mutex.get_mut().unwrap() = 10;
/// assert_eq!(*mutex.lock().unwrap(), 10);
/// ```
#[inline]
pub fn get_mut(&mut self) -> LockResult<&mut T> {
let x = unsafe { &mut *self.value.get() };
if self.is_poisoned() {
Err(PoisonError::new(x))
} else {
Ok(x)
}
}
/// Consumes this mutex, returning the underlying data.
///
/// # Errors
///
/// If another user of this mutex panicked while holding the mutex, then
/// this call will return an error instead.
///
/// # Examples
///
/// ```
/// use sync_2::Mutex;
///
/// let mutex = Mutex::new(0);
/// assert_eq!(mutex.into_inner().unwrap(), 0);
/// ```
#[inline]
pub fn into_inner(self) -> LockResult<T> {
if self.is_poisoned() {
Err(PoisonError::new(self.value.into_inner()))
} else {
Ok(self.value.into_inner())
}
}
}
impl<T> !Send for MutexGuard<'_, T> {}
unsafe impl<T: Sync> Sync for MutexGuard<'_, T> {}
/// Unique guard created by the method [`Mutex::lock`] and [`Mutex::try_lock`].
pub struct MutexGuard<'a, T> {
lock: &'a Mutex<T>,
}
impl<'a, T> Deref for MutexGuard<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.value.get() }
}
}
impl<'a, T> DerefMut for MutexGuard<'a, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.lock.value.get() }
}
}
impl<'a, T> Drop for MutexGuard<'a, T> {
#[inline]
fn drop(&mut self) {
if panicking() {
self.lock.ref_count.fetch_or(POISON_M, SeqCst);
}
self.lock.ref_count.fetch_sub(LOCK, SeqCst);
}
}
impl<'a, T: Seek> Seek for MutexGuard<'a, T> {
#[inline]
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
(**self).seek(pos)
}
}
impl<'a, T: Write> Write for MutexGuard<'a, T> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
(**self).write(buf)
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
(**self).flush()
}
}
impl<'a, T: Read> Read for MutexGuard<'a, T> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(**self).read(buf)
}
}
impl<'a, T: BufRead> BufRead for MutexGuard<'a, T> {
#[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> {
(**self).fill_buf()
}
#[inline]
fn consume(&mut self, amt: usize) {
(**self).consume(amt)
}
}
impl<'a, T: AsRef<U>, U> AsRef<U> for MutexGuard<'a, T> {
fn as_ref(&self) -> &U {
(**self).as_ref()
}
}
impl<'a, T: AsMut<U>, U> AsMut<U> for MutexGuard<'a, T> {
fn as_mut(&mut self) -> &mut U {
(**self).as_mut()
}
}
/// An allocation-free [`RwLock`][`std::sync::RwLock`] made in pure Rust.
pub struct RwLock<T> {
value: UnsafeCell<T>,
ref_count: AtomicUsize,
}
unsafe impl<T: Send> Send for RwLock<T> {}
unsafe impl<T: Send> Sync for RwLock<T> {}
impl<T> RwLock<T> {
/// Creates a new `RwLock` locking the value `x`.
///
/// This function it's constant only without `debug_assertions` due to declare a thread local
/// storage to avoid acquire the lock twice from the same thread.
#[inline]
pub const fn new(x: T) -> Self {
Self {
value: UnsafeCell::new(x),
ref_count: AtomicUsize::new(0),
}
}
/// Locks this rwlock with shared read access, blocking the current thread
/// until it can be acquired.
///
/// The calling thread will be blocked until there are no more writers which
/// hold the lock. There may be other readers currently inside the lock when
/// this method returns. This method does not provide any guarantees with
/// respect to the ordering of whether contentious readers or writers will
/// acquire the lock first.
///
/// Returns an RAII guard which will release this thread's shared access
/// once it is dropped.
///
/// # Errors
///
/// This function will return an error if the `RwLock` is poisoned. An `RwLock`
/// is poisoned whenever a writer panics while holding an exclusive lock.
/// The failure will occur immediately after the lock has been acquired.
///
/// # Panics
///
/// This function panic when called if the lock is already held by the current thread with `debug_assertions` on.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use std::thread;
/// use sync_2::RwLock;
///
/// let lock = Arc::new(RwLock::new(1));
/// let c_lock = lock.clone();
///
/// let n = lock.read().unwrap();
/// assert_eq!(*n, 1);
///
/// thread::spawn(move || {
/// let r = c_lock.read();
/// assert!(r.is_ok());
/// }).join().unwrap();
/// ```
#[inline]
pub fn read(&self) -> LockResult<SharedGuard<'_, T>> {
loop {
match self.try_read() {
Ok(e) => break Ok(e),
Err(WouldBlock) => spin_loop(),
Err(Poisoned(e)) => break Err(e),
}
}
}
/// Locks this rwlock with exclusive write access, blocking the current
/// thread until it can be acquired.
///
/// This function will not return while other writers or other readers
/// currently have access to the lock.
///
/// Returns an RAII guard which will drop the write access of this rwlock
/// when dropped.
///
/// # Errors
///
/// This function will return an error if the `RwLock` is poisoned. An `RwLock`
/// is poisoned whenever a writer panics while holding an exclusive lock.
/// An error will be returned when the lock is acquired.
///
/// # Panics
///
/// This function panic when called if the lock is already held by the current thread with `debug_assertions` on.
///
/// # Examples
///
/// ```
/// use sync_2::RwLock;
///
/// let lock = RwLock::new(1);
///
/// let mut n = lock.write().unwrap();
/// *n = 2;
///
/// assert!(lock.try_read().is_err());
/// ```
#[inline]
pub fn write(&self) -> LockResult<UniqueGuard<'_, T>> {
loop {
match self.try_write() {
Ok(e) => break Ok(e),
Err(WouldBlock) => spin_loop(),
Err(Poisoned(e)) => break Err(e),
}
}
}
/// Attempts to acquire this rwlock with shared read access.
///
/// If the access could not be granted at this time, then `Err` is returned.
/// Otherwise, an RAII guard is returned which will release the shared access
/// when it is dropped.
///
/// This function does not block.
///
/// This function does not provide any guarantees with respect to the ordering
/// of whether contentious readers or writers will acquire the lock first.
///
/// # Errors
///
/// This function will return an error if the `RwLock` is poisoned. An `RwLock`
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
///
/// # Examples
///
/// ```
/// use sync_2::RwLock;
///
/// let lock = RwLock::new(1);
///
/// match lock.try_read() {
/// Ok(n) => assert_eq!(*n, 1),
/// Err(_) => unreachable!(),
/// };
/// ```
pub fn try_read(&self) -> TryLockResult<SharedGuard<'_, T>> {
let x = match self.ref_count.fetch_update(
SeqCst,
SeqCst,
|x| if x < WRITE { Some(x + 1) } else { None },
) {
Ok(x) => x,
Err(_) => return Err(WouldBlock),
};
// WRITE it's greater than poison,once we know our value it's less than WRITE it is ok to not filter bits as in `is_poisoned`
if x < POISON {
Ok(SharedGuard { lock: self })
} else {
Err(Poisoned(PoisonError::new(SharedGuard { lock: self })))
}
}
/// Attempts to lock this rwlock with exclusive write access.
///
/// If the lock could not be acquired at this time, then `Err` is returned.
/// Otherwise, an RAII guard is returned which will release the lock when
/// it is dropped.
///
/// This function does not block.
///
/// This function does not provide any guarantees with respect to the ordering
/// of whether contentious readers or writers will acquire the lock first.
///
/// # Errors
///
/// This function will return an error if the `RwLock` is poisoned. An `RwLock`
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
///
/// # Examples
///
/// ```
/// use sync_2::RwLock;
///
/// let lock = RwLock::new(1);
///
/// let n = lock.read().unwrap();
/// assert_eq!(*n, 1);
///
/// println!("{:?}", lock);
/// assert!(lock.try_write().is_err());
/// ```
pub fn try_write(&self) -> TryLockResult<UniqueGuard<'_, T>> {
let mut clean = true;
match self.ref_count.fetch_update(
SeqCst,
SeqCst,
|x| {
if x == 0 || {
clean = false;
x == POISON
} {
Some(x | WRITE)
} else {
None
}
},
) {
Ok(x) => x,
Err(_) => return Err(WouldBlock),
};
if clean {
Ok(UniqueGuard { lock: self })
} else {
Err(Poisoned(PoisonError::new(UniqueGuard { lock: self })))
}
}
/// Determines whether the lock is poisoned.
///
/// If another thread is active, the lock can still become poisoned at any
/// time. You should not trust a `false` value for program correctness
/// without additional synchronization.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use std::thread;
/// use sync_2::RwLock;
///
/// let lock = Arc::new(RwLock::new(0));
/// let c_lock = lock.clone();
///
/// let _ = thread::spawn(move || {
/// let _lock = c_lock.write().unwrap();
/// panic!(); // the lock gets poisoned
/// }).join();
/// assert_eq!(lock.is_poisoned(), true);
/// ```
#[inline]
pub fn is_poisoned(&self) -> bool {
(self.ref_count.load(SeqCst) & POISON) == POISON
}
/// Returns a mutable reference to the underlying data.
///
/// Since this call borrows the `RwLock` mutably, no actual locking needs to
/// take place -- the mutable borrow statically guarantees no locks exist.
///
/// # Errors
///
/// This function will return an error if the `RwLock` is poisoned. An `RwLock`
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
///
/// # Examples
///
/// ```
/// use sync_2::RwLock;
///
/// let mut lock = RwLock::new(0);
/// *lock.get_mut().unwrap() = 10;
/// assert_eq!(*lock.read().unwrap(), 10);
/// ```
#[inline]
pub fn get_mut(&mut self) -> LockResult<&mut T> {
let x = unsafe { &mut *self.value.get() };
if self.is_poisoned() {
Err(PoisonError::new(x))
} else {
Ok(x)
}
}
/// Consumes this `RwLock`, returning the underlying data.
///
/// # Errors
///
/// This function will return an error if the `RwLock` is poisoned. An `RwLock`
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
///
/// # Examples
///
/// ```
/// use sync_2::RwLock;
///
/// let lock = RwLock::new(String::new());
/// {
/// let mut s = lock.write().unwrap();
/// *s = "modified".to_owned();
/// }
/// assert_eq!(lock.into_inner().unwrap(), "modified");
/// ```
#[inline]
pub fn into_inner(self) -> LockResult<T> {
if self.is_poisoned() {
Err(PoisonError::new(self.value.into_inner()))
} else {
Ok(self.value.into_inner())
}
}
}
use core::fmt;
impl<T: fmt::Debug> fmt::Debug for RwLock<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.try_read() {
Ok(guard) => f.debug_struct("RwLock").field("data", &&*guard).finish(),
Err(Poisoned(err)) => f
.debug_struct("RwLock")
.field("data", &&**err.get_ref())
.finish(),
Err(WouldBlock) => {
struct LockedPlaceholder;
impl fmt::Debug for LockedPlaceholder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("<locked>")
}
}
f.debug_struct("RwLock")
.field("data", &LockedPlaceholder)
.finish()
}
}
}
}
impl<T: Default> Default for RwLock<T> {
/// Creates a new `RwLock<T>`, with the `Default` value for T.
fn default() -> Self {
Self::new(T::default())
}
}
impl<T> From<T> for RwLock<T> {
/// Creates a new instance of an `RwLock<T>` which is unlocked.
/// This is equivalent to [`RwLock::new`].
///
/// [`RwLock::new`]: #method.new
fn from(t: T) -> Self {
Self::new(t)
}
}
/// Read-only shared guard created by the methods [`RwLock::read`] and [`RwLock::try_read`].
///
/// Leaking this struct would cause deadlock with any further call to [`RwLock::write`].
pub struct SharedGuard<'a, T> {
lock: &'a RwLock<T>,
}
impl<T: fmt::Debug> fmt::Debug for SharedGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RwLockReadGuard")
.field("lock", self.lock)
.finish()
}
}
impl<T: fmt::Display> fmt::Display for SharedGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T: fmt::Debug> fmt::Debug for UniqueGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RwLockWriteGuard")
.field("lock", self.lock)
.finish()
}
}
impl<T: fmt::Display> fmt::Display for UniqueGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<'a, T> Drop for SharedGuard<'a, T> {
#[inline]
fn drop(&mut self) {
self.lock.ref_count.fetch_sub(1, SeqCst);
}
}
impl<'a, T> Deref for SharedGuard<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.value.get() }
}
}
impl<T> !Send for SharedGuard<'_, T> {}
unsafe impl<T: Sync> Sync for SharedGuard<'_, T> {}
impl<T> !Send for UniqueGuard<'_, T> {}
unsafe impl<T: Sync> Sync for UniqueGuard<'_, T> {}
/// Unique guard created by the methods [`RwLock::write`] and [`RwLock::try_write`].
///
/// Leaking this struct would cause deadlock with any further call to [`RwLock::write`] or [`RwLock::read`].
pub struct UniqueGuard<'a, T> {
lock: &'a RwLock<T>,
}
impl<'a, T> Deref for UniqueGuard<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.value.get() }
}
}
impl<'a, T> DerefMut for UniqueGuard<'a, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.lock.value.get() }
}
}
impl<'a, T> Drop for UniqueGuard<'a, T> {
#[inline]
fn drop(&mut self) {
if panicking() {
self.lock.ref_count.fetch_or(POISON, SeqCst);
}
self.lock.ref_count.fetch_xor(WRITE, SeqCst);
}
}
impl<'a, T: Seek> Seek for UniqueGuard<'a, T> {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
(**self).seek(pos)
}
}
impl<'a, T: Write> Write for UniqueGuard<'a, T> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
(**self).write(buf)
}
fn flush(&mut self) -> io::Result<()> {
(**self).flush()
}
}
impl<'a, T: Read> Read for UniqueGuard<'a, T> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(**self).read(buf)
}
}
impl<'a, T: BufRead> BufRead for UniqueGuard<'a, T> {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
(**self).fill_buf()
}
fn consume(&mut self, amt: usize) {
(**self).consume(amt)
}
}
}
mod thread_local_a {
use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
use core::sync::atomic::{spin_loop_hint as spin_loop, AtomicU8, AtomicUsize, Ordering::SeqCst};
use std::io::{self, BufRead, Read, Seek, SeekFrom, Write};
use std::sync::{
LockResult, PoisonError,
TryLockError::{Poisoned, WouldBlock},
TryLockResult,
};
use std::thread::panicking;
use std::sync::atomic::Ordering::Relaxed;
use thread_local::ThreadLocal;
use super::non_thread_local;
// sentinel most significant bit,write lock
const WRITE: usize = usize::MAX - (usize::MAX / 2);
// sentinel pen-most significant bit,poisoned state
const POISON: usize = WRITE / 2;
/// An allocation-free [`RwLock`][`std::sync::RwLock`] made in pure Rust.
pub struct RwLock<T> {
value: UnsafeCell<T>,
ref_count: AtomicUsize,
local_ref_count: non_thread_local::Mutex<Option<ThreadLocal<AtomicUsize>>>,
}
unsafe impl<T: Send> Send for RwLock<T> {}
unsafe impl<T: Send> Sync for RwLock<T> {}
impl<T> RwLock<T> {
/// Creates a new `RwLock` locking the value `x`.
#[inline]
pub const fn new(x: T) -> Self {
Self {
value: UnsafeCell::new(x),
ref_count: AtomicUsize::new(0),
local_ref_count: non_thread_local::Mutex::new(None),
}
}
/// Locks this rwlock with shared read access, blocking the current thread
/// until it can be acquired.
///
/// The calling thread will be blocked until there are no more writers which
/// hold the lock. There may be other readers currently inside the lock when
/// this method returns. This method does not provide any guarantees with
/// respect to the ordering of whether contentious readers or writers will
/// acquire the lock first.
///
/// Returns an RAII guard which will release this thread's shared access
/// once it is dropped.
///
/// # Errors
///
/// This function will return an error if the `RwLock` is poisoned. An `RwLock`
/// is poisoned whenever a writer panics while holding an exclusive lock.
/// The failure will occur immediately after the lock has been acquired.
///
/// # Panics
///
/// This function panic when called if the lock is already held by the current thread with `debug_assertions` on.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use std::thread;
/// use sync_2::RwLock;
///
/// let lock = Arc::new(RwLock::new(1));
/// let c_lock = lock.clone();
///
/// let n = lock.read().unwrap();
/// assert_eq!(*n, 1);
///
/// thread::spawn(move || {
/// let r = c_lock.read();
/// assert!(r.is_ok());
/// }).join().unwrap();
/// ```
#[inline]
pub fn read(&self) -> LockResult<SharedGuard<'_, T>> {
let mut x = self.local_ref_count.lock().unwrap();
if x.get_or_insert_with(ThreadLocal::new).get_or(|| AtomicUsize::new(0)).load(Relaxed) >= WRITE {
panic!("rwlock read lock would result in deadlock")
}
x.get_or_insert_with(ThreadLocal::new).get_or(|| AtomicUsize::new(0)).fetch_add(1, Relaxed);
loop {
match self.try_read() {
Ok(e) => break Ok(e),
Err(WouldBlock) => spin_loop(),
Err(Poisoned(e)) => break Err(e),
}
}
}
/// Locks this rwlock with exclusive write access, blocking the current
/// thread until it can be acquired.
///
/// This function will not return while other writers or other readers
/// currently have access to the lock.
///
/// Returns an RAII guard which will drop the write access of this rwlock
/// when dropped.
///
/// # Errors
///
/// This function will return an error if the `RwLock` is poisoned. An `RwLock`
/// is poisoned whenever a writer panics while holding an exclusive lock.
/// An error will be returned when the lock is acquired.
///
/// # Panics
///
/// This function panic when called if the lock is already held by the current thread with `debug_assertions` on.
///
/// # Examples
///
/// ```
/// use sync_2::RwLock;
///
/// let lock = RwLock::new(1);
///
/// let mut n = lock.write().unwrap();
/// *n = 2;
///
/// assert!(lock.try_read().is_err());
/// ```
#[inline]
pub fn write(&self) -> LockResult<UniqueGuard<'_, T>> {
let mut x = self.local_ref_count.lock().unwrap();
if x.get_or_insert_with(ThreadLocal::new).get_or(|| AtomicUsize::new(0)).load(Relaxed) != 0 {
panic!("rwlock read lock would result in deadlock")
}
x.get_or_insert_with(ThreadLocal::new).get_or(|| AtomicUsize::new(0)).fetch_or(WRITE, Relaxed);
loop {
match self.try_write() {
Ok(e) => break Ok(e),
Err(WouldBlock) => spin_loop(),
Err(Poisoned(e)) => break Err(e),
}
}
}
/// Attempts to acquire this rwlock with shared read access.
///
/// If the access could not be granted at this time, then `Err` is returned.
/// Otherwise, an RAII guard is returned which will release the shared access
/// when it is dropped.
///
/// This function does not block.
///
/// This function does not provide any guarantees with respect to the ordering
/// of whether contentious readers or writers will acquire the lock first.
///
/// # Errors
///
/// This function will return an error if the `RwLock` is poisoned. An `RwLock`
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
///
/// # Examples
///
/// ```
/// use sync_2::RwLock;
///
/// let lock = RwLock::new(1);
///
/// match lock.try_read() {
/// Ok(n) => assert_eq!(*n, 1),
/// Err(_) => unreachable!(),
/// };
/// ```
pub fn try_read(&self) -> TryLockResult<SharedGuard<'_, T>> {
let x = match self.ref_count.fetch_update(
SeqCst,
SeqCst,
|x| if x < WRITE { Some(x + 1) } else { None },
) {
Ok(x) => x,
Err(_) => return Err(WouldBlock),
};
// WRITE it's greater than poison,once we know our value it's less than WRITE it is ok to not filter bits as in `is_poisoned`
if x < POISON {
Ok(SharedGuard { lock: self })
} else {
Err(Poisoned(PoisonError::new(SharedGuard { lock: self })))
}
}
/// Attempts to lock this rwlock with exclusive write access.
///
/// If the lock could not be acquired at this time, then `Err` is returned.
/// Otherwise, an RAII guard is returned which will release the lock when
/// it is dropped.
///
/// This function does not block.
///
/// This function does not provide any guarantees with respect to the ordering
/// of whether contentious readers or writers will acquire the lock first.
///
/// # Errors
///
/// This function will return an error if the `RwLock` is poisoned. An `RwLock`
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
///
/// # Examples
///
/// ```
/// use sync_2::RwLock;
///
/// let lock = RwLock::new(1);
///
/// let n = lock.read().unwrap();
/// assert_eq!(*n, 1);
///
/// println!("{:?}", lock);
/// assert!(lock.try_write().is_err());
/// ```
pub fn try_write(&self) -> TryLockResult<UniqueGuard<'_, T>> {
let mut clean = true;
match self.ref_count.fetch_update(
SeqCst,
SeqCst,
|x| {
if x == 0 || {
clean = false;
x == POISON
} {
Some(x | WRITE)
} else {
None
}
},
) {
Ok(x) => x,
Err(_) => return Err(WouldBlock),
};
if clean {
Ok(UniqueGuard { lock: self })
} else {
Err(Poisoned(PoisonError::new(UniqueGuard { lock: self })))
}
}
/// Determines whether the lock is poisoned.
///
/// If another thread is active, the lock can still become poisoned at any
/// time. You should not trust a `false` value for program correctness
/// without additional synchronization.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use std::thread;
/// use sync_2::RwLock;
///
/// let lock = Arc::new(RwLock::new(0));
/// let c_lock = lock.clone();
///
/// let _ = thread::spawn(move || {
/// let _lock = c_lock.write().unwrap();
/// panic!(); // the lock gets poisoned
/// }).join();
/// assert_eq!(lock.is_poisoned(), true);
/// ```
#[inline]
pub fn is_poisoned(&self) -> bool {
(self.ref_count.load(SeqCst) & POISON) == POISON
}
/// Returns a mutable reference to the underlying data.
///
/// Since this call borrows the `RwLock` mutably, no actual locking needs to
/// take place -- the mutable borrow statically guarantees no locks exist.
///
/// # Errors
///
/// This function will return an error if the `RwLock` is poisoned. An `RwLock`
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
///
/// # Examples
///
/// ```
/// use sync_2::RwLock;
///
/// let mut lock = RwLock::new(0);
/// *lock.get_mut().unwrap() = 10;
/// assert_eq!(*lock.read().unwrap(), 10);
/// ```
#[inline]
pub fn get_mut(&mut self) -> LockResult<&mut T> {
let x = unsafe { &mut *self.value.get() };
if self.is_poisoned() {
Err(PoisonError::new(x))
} else {
Ok(x)
}
}
/// Consumes this `RwLock`, returning the underlying data.
///
/// # Errors
///
/// This function will return an error if the `RwLock` is poisoned. An `RwLock`
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
///
/// # Examples
///
/// ```
/// use sync_2::RwLock;
///
/// let lock = RwLock::new(String::new());
/// {
/// let mut s = lock.write().unwrap();
/// *s = "modified".to_owned();
/// }
/// assert_eq!(lock.into_inner().unwrap(), "modified");
/// ```
#[inline]
pub fn into_inner(self) -> LockResult<T> {
if self.is_poisoned() {
Err(PoisonError::new(self.value.into_inner()))
} else {
Ok(self.value.into_inner())
}
}
}
use core::fmt;
impl<T: fmt::Debug> fmt::Debug for RwLock<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.try_read() {
Ok(guard) => f.debug_struct("RwLock").field("data", &&*guard).finish(),
Err(Poisoned(err)) => f
.debug_struct("RwLock")
.field("data", &&**err.get_ref())
.finish(),
Err(WouldBlock) => {
struct LockedPlaceholder;
impl fmt::Debug for LockedPlaceholder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("<locked>")
}
}
f.debug_struct("RwLock")
.field("data", &LockedPlaceholder)
.finish()
}
}
}
}
impl<T: Default> Default for RwLock<T> {
/// Creates a new `RwLock<T>`, with the `Default` value for T.
fn default() -> Self {
Self::new(T::default())
}
}
impl<T> From<T> for RwLock<T> {
/// Creates a new instance of an `RwLock<T>` which is unlocked.
/// This is equivalent to [`RwLock::new`].
///
/// [`RwLock::new`]: #method.new
fn from(t: T) -> Self {
Self::new(t)
}
}
/// Read-only shared guard created by the methods [`RwLock::read`] and [`RwLock::try_read`].
///
/// Leaking this struct would cause deadlock with any further call to [`RwLock::write`].
pub struct SharedGuard<'a, T> {
lock: &'a RwLock<T>,
}
impl<T: fmt::Debug> fmt::Debug for SharedGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RwLockReadGuard")
.field("lock", self.lock)
.finish()
}
}
impl<T: fmt::Display> fmt::Display for SharedGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T: fmt::Debug> fmt::Debug for UniqueGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RwLockWriteGuard")
.field("lock", self.lock)
.finish()
}
}
impl<T: fmt::Display> fmt::Display for UniqueGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<'a, T> Drop for SharedGuard<'a, T> {
#[inline]
fn drop(&mut self) {
self.lock.ref_count.fetch_sub(1, SeqCst);
self.lock
.local_ref_count.lock().unwrap().get_or_insert_with(ThreadLocal::new)
.get_or(|| AtomicUsize::new(0))
.fetch_sub(1, Relaxed);
}
}
impl<'a, T> Deref for SharedGuard<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.value.get() }
}
}
impl<T> !Send for SharedGuard<'_, T> {}
unsafe impl<T: Sync> Sync for SharedGuard<'_, T> {}
impl<T> !Send for UniqueGuard<'_, T> {}
unsafe impl<T: Sync> Sync for UniqueGuard<'_, T> {}
/// Unique guard created by the methods [`RwLock::write`] and [`RwLock::try_write`].
///
/// Leaking this struct would cause deadlock with any further call to [`RwLock::write`] or [`RwLock::read`].
pub struct UniqueGuard<'a, T> {
lock: &'a RwLock<T>,
}
impl<'a, T> Deref for UniqueGuard<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.value.get() }
}
}
impl<'a, T> DerefMut for UniqueGuard<'a, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.lock.value.get() }
}
}
impl<'a, T> Drop for UniqueGuard<'a, T> {
#[inline]
fn drop(&mut self) {
if panicking() {
self.lock.ref_count.fetch_or(POISON, SeqCst);
}
self.lock.ref_count.fetch_xor(WRITE, SeqCst);
self.lock
.local_ref_count.lock().unwrap().get_or_insert_with(ThreadLocal::new)
.get_or(|| AtomicUsize::new(0))
.fetch_xor(WRITE, Relaxed);
}
}
impl<'a, T: Seek> Seek for UniqueGuard<'a, T> {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
(**self).seek(pos)
}
}
impl<'a, T: Write> Write for UniqueGuard<'a, T> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
(**self).write(buf)
}
fn flush(&mut self) -> io::Result<()> {
(**self).flush()
}
}
impl<'a, T: Read> Read for UniqueGuard<'a, T> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(**self).read(buf)
}
}
impl<'a, T: BufRead> BufRead for UniqueGuard<'a, T> {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
(**self).fill_buf()
}
fn consume(&mut self, amt: usize) {
(**self).consume(amt)
}
}
const LOCK: u8 = 2;
const POISON_M: u8 = 1;
/// An allocation-free [`Mutex`][`std::sync::Mutex`] made in pure Rust.
pub struct Mutex<T> {
value: UnsafeCell<T>,
ref_count: AtomicU8,
// local ref_count used to detect deadlock whenever you try to acquire a lock that was blocked on the current thread on debug
local_ref_count: non_thread_local::Mutex<Option<ThreadLocal<AtomicU8>>>,
}
unsafe impl<T: Send> Send for Mutex<T> {}
unsafe impl<T: Send> Sync for Mutex<T> {}
impl<T> Mutex<T> {
/// Creates a new mutex in an unlocked state ready for use.
#[inline]
pub const fn new(x: T) -> Self {
Self {
value: UnsafeCell::new(x),
ref_count: AtomicU8::new(0),
local_ref_count: non_thread_local::Mutex::new(None),
}
}
/// Acquires a mutex, blocking the current thread until it is able to do so.
///
/// This function will block the local thread until it is available to acquire
/// the mutex. Upon returning, the thread is the only thread with the lock
/// held. An RAII guard is returned to allow scoped unlock of the lock. When
/// the guard goes out of scope, the mutex will be unlocked.
///
/// The exact behavior on locking a mutex in the thread which already holds
/// the lock is left unspecified. However, this function will not return on
/// the second call (it might panic or deadlock, for example).
///
/// # Errors
///
/// If another user of this mutex panicked while holding the mutex, then
/// this call will return an error once the mutex is acquired.
///
/// # Panics
///
/// This function might panic when called if the lock is already held by
/// the current thread only with `debug_assertions`.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use sync_2::Mutex;
/// use std::thread;
///
/// let mutex = Arc::new(Mutex::new(0));
/// let c_mutex = mutex.clone();
///
/// thread::spawn(move || {
/// *c_mutex.lock().unwrap() = 10;
/// }).join().expect("thread::spawn failed");
/// assert_eq!(*mutex.lock().unwrap(), 10);
/// ```
#[inline]
pub fn lock(&self) -> LockResult<MutexGuard<'_, T>> {
if self
.local_ref_count.lock().unwrap().get_or_insert_with(ThreadLocal::new)
.get_or(|| AtomicU8::new(0))
.fetch_or(LOCK, Relaxed)
== LOCK
{
panic!("mutex lock would result in deadlock")
}
loop {
match self.try_lock() {
Ok(e) => break Ok(e),
Err(WouldBlock) => spin_loop(),
Err(Poisoned(e)) => break Err(e),
}
}
}
/// Attempts to acquire this lock.
///
/// If the lock could not be acquired at this time, then [`Err`] is returned.
/// Otherwise, an RAII guard is returned. The lock will be unlocked when the
/// guard is dropped.
///
/// This function does not block.
///
/// # Errors
///
/// If another user of this mutex panicked while holding the mutex, then
/// this call will return failure if the mutex would otherwise be
/// acquired.
///
/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use sync_2::Mutex;
/// use std::thread;
///
/// let mutex = Arc::new(Mutex::new(0));
/// let c_mutex = mutex.clone();
///
/// thread::spawn(move || {
/// let mut lock = c_mutex.try_lock();
/// if let Ok(ref mut mutex) = lock {
/// **mutex = 10;
/// } else {
/// println!("try_lock failed");
/// }
/// }).join().expect("thread::spawn failed");
/// assert_eq!(*mutex.lock().unwrap(), 10);
/// ```
pub fn try_lock(&self) -> TryLockResult<MutexGuard<'_, T>> {
let x = match self.ref_count.fetch_update(
SeqCst,
SeqCst,
|x| if x < LOCK { Some(x | LOCK) } else { None },
) {
Ok(x) => x,
Err(_) => return Err(WouldBlock),
};
if x < POISON_M {
Ok(MutexGuard { lock: self })
} else {
Err(Poisoned(PoisonError::new(MutexGuard { lock: self })))
}
}
/// Determines whether the mutex is poisoned.
///
/// If another thread is active, the mutex can still become poisoned at any
/// time. You should not trust a `false` value for program correctness
/// without additional synchronization.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use sync_2::Mutex;
/// use std::thread;
///
/// let mutex = Arc::new(Mutex::new(0));
/// let c_mutex = mutex.clone();
///
/// let _ = thread::spawn(move || {
/// let _lock = c_mutex.lock().unwrap();
/// panic!(); // the mutex gets poisoned
/// }).join();
/// assert_eq!(mutex.is_poisoned(), true);
/// ```
#[inline]
pub fn is_poisoned(&self) -> bool {
(self.ref_count.load(SeqCst) & POISON_M) == POISON_M
}
/// Returns a mutable reference to the underlying data.
///
/// Since this call borrows the `Mutex` mutably, no actual locking needs to
/// take place -- the mutable borrow statically guarantees no locks exist.
///
/// # Errors
///
/// If another user of this mutex panicked while holding the mutex, then
/// this call will return an error instead.
///
/// # Examples
///
/// ```
/// use sync_2::Mutex;
///
/// let mut mutex = Mutex::new(0);
/// *mutex.get_mut().unwrap() = 10;
/// assert_eq!(*mutex.lock().unwrap(), 10);
/// ```
#[inline]
pub fn get_mut(&mut self) -> LockResult<&mut T> {
let x = unsafe { &mut *self.value.get() };
if self.is_poisoned() {
Err(PoisonError::new(x))
} else {
Ok(x)
}
}
/// Consumes this mutex, returning the underlying data.
///
/// # Errors
///
/// If another user of this mutex panicked while holding the mutex, then
/// this call will return an error instead.
///
/// # Examples
///
/// ```
/// use sync_2::Mutex;
///
/// let mutex = Mutex::new(0);
/// assert_eq!(mutex.into_inner().unwrap(), 0);
/// ```
#[inline]
pub fn into_inner(self) -> LockResult<T> {
if self.is_poisoned() {
Err(PoisonError::new(self.value.into_inner()))
} else {
Ok(self.value.into_inner())
}
}
}
impl<T> !Send for MutexGuard<'_, T> {}
unsafe impl<T: Sync> Sync for MutexGuard<'_, T> {}
/// Unique guard created by the method [`Mutex::lock`] and [`Mutex::try_lock`].
pub struct MutexGuard<'a, T> {
lock: &'a Mutex<T>,
}
impl<'a, T> Deref for MutexGuard<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.value.get() }
}
}
impl<'a, T> DerefMut for MutexGuard<'a, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.lock.value.get() }
}
}
impl<'a, T> Drop for MutexGuard<'a, T> {
#[inline]
fn drop(&mut self) {
if panicking() {
self.lock.ref_count.fetch_or(POISON_M, SeqCst);
}
self.lock.ref_count.fetch_sub(LOCK, SeqCst);
self.lock
.local_ref_count.lock().unwrap().get_or_insert_with(ThreadLocal::new)
.get_or(|| AtomicU8::new(0))
.fetch_sub(LOCK, Relaxed);
}
}
impl<'a, T: Seek> Seek for MutexGuard<'a, T> {
#[inline]
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
(**self).seek(pos)
}
}
impl<'a, T: Write> Write for MutexGuard<'a, T> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
(**self).write(buf)
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
(**self).flush()
}
}
impl<'a, T: Read> Read for MutexGuard<'a, T> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(**self).read(buf)
}
}
impl<'a, T: BufRead> BufRead for MutexGuard<'a, T> {
#[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> {
(**self).fill_buf()
}
#[inline]
fn consume(&mut self, amt: usize) {
(**self).consume(amt)
}
}
impl<'a, T: AsRef<U>, U> AsRef<U> for MutexGuard<'a, T> {
fn as_ref(&self) -> &U {
(**self).as_ref()
}
}
impl<'a, T: AsMut<U>, U> AsMut<U> for MutexGuard<'a, T> {
fn as_mut(&mut self) -> &mut U {
(**self).as_mut()
}
}
}
#[cfg(not(debug_assertions))]
pub use non_thread_local::*;
#[cfg(debug_assertions)]
pub use thread_local_a::*;