1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#![doc = include_str!("../README.md")]
#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]

// Re-export this so that our users can use the same version we do.
#[cfg(feature = "lock_api")]
pub use lock_api;

// If we don't have the real `lock_api` crate, use our polyfills.
#[cfg(not(feature = "lock_api"))]
pub mod lock_api;

// Export convenient `Mutex` and `RwLock` types.
#[cfg(feature = "lock_api")]
pub type Mutex<T> = lock_api::Mutex<RawMutex, T>;
#[cfg(feature = "lock_api")]
pub type RwLock<T> = lock_api::RwLock<RawRwLock, T>;
#[cfg(feature = "lock_api")]
pub type MutexGuard<'a, T> = lock_api::MutexGuard<'a, RawMutex, T>;
#[cfg(feature = "lock_api")]
pub type MappedMutexGuard<'a, T> = lock_api::MappedMutexGuard<'a, RawMutex, T>;
#[cfg(feature = "lock_api")]
pub type RwLockReadGuard<'a, T> = lock_api::RwLockReadGuard<'a, RawRwLock, T>;
#[cfg(feature = "lock_api")]
pub type RwLockWriteGuard<'a, T> = lock_api::RwLockWriteGuard<'a, RawRwLock, T>;
#[cfg(feature = "lock_api")]
pub type MappedRwLockReadGuard<'a, T> = lock_api::MappedRwLockReadGuard<'a, RawRwLock, T>;
#[cfg(feature = "lock_api")]
pub type MappedRwLockWriteGuard<'a, T> = lock_api::MappedRwLockWriteGuard<'a, RawRwLock, T>;
#[cfg(feature = "lock_api")]
#[cfg(feature = "atomic_usize")]
#[cfg_attr(docsrs, doc(cfg(feature = "atomic_usize")))]
pub type ReentrantMutex<G, T> = lock_api::ReentrantMutex<RawMutex, G, T>;
#[cfg(feature = "lock_api")]
#[cfg(feature = "atomic_usize")]
#[cfg_attr(docsrs, doc(cfg(feature = "atomic_usize")))]
pub type ReentrantMutexGuard<'a, G, T> = lock_api::ReentrantMutexGuard<'a, RawMutex, G, T>;

// Export the once types.
pub use once::{Once, OnceState};
pub use once_lock::OnceLock;

// Export the condvar types.
#[cfg(feature = "lock_api")]
pub use condvar::{Condvar, WaitTimeoutResult};

// Export the raw condvar types.
pub use futex_condvar::Condvar as RawCondvar;

// std's implementation code.
#[cfg(feature = "lock_api")]
mod condvar;
mod futex_condvar;
mod futex_mutex;
mod futex_once;
mod futex_rwlock;
mod once;
mod once_lock;
mod wait_wake;

/// An implementation of [`lock_api::RawMutex`].
///
/// All of this `RawMutex`'s methods are in its implementation of
/// [`lock_api::RawMutex`]. To import that trait without conflicting
/// with this `RawMutex` type, use:
///
/// ```
/// use rustix_futex_sync::lock_api::RawMutex as _;
/// ```
#[repr(transparent)]
pub struct RawMutex(futex_mutex::Mutex);

/// An implementation of [`lock_api::RawRwLock`].
///
/// All of this `RawRwLock`'s methods are in its implementation of
/// [`lock_api::RawRwLock`]. To import that trait without conflicting
/// with this `RawRwLock` type, use:
///
/// ```
/// use rustix_futex_sync::lock_api::RawRwLock as _;
/// ```
#[repr(C)]
pub struct RawRwLock(futex_rwlock::RwLock);

// Implement the raw lock traits for our wrappers.

unsafe impl lock_api::RawMutex for RawMutex {
    type GuardMarker = lock_api::GuardNoSend;

    const INIT: Self = Self(futex_mutex::Mutex::new());

    #[inline]
    fn lock(&self) {
        self.0.lock()
    }

    #[inline]
    fn try_lock(&self) -> bool {
        self.0.try_lock()
    }

    #[inline]
    unsafe fn unlock(&self) {
        self.0.unlock()
    }
}

unsafe impl lock_api::RawRwLock for RawRwLock {
    type GuardMarker = lock_api::GuardNoSend;

    const INIT: Self = Self(futex_rwlock::RwLock::new());

    #[inline]
    fn lock_shared(&self) {
        self.0.read()
    }

    #[inline]
    fn try_lock_shared(&self) -> bool {
        self.0.try_read()
    }

    #[inline]
    unsafe fn unlock_shared(&self) {
        self.0.read_unlock()
    }

    #[inline]
    fn lock_exclusive(&self) {
        self.0.write()
    }

    #[inline]
    fn try_lock_exclusive(&self) -> bool {
        self.0.try_write()
    }

    #[inline]
    unsafe fn unlock_exclusive(&self) {
        self.0.write_unlock()
    }
}