1pub(crate) mod mutex;
2pub(crate) mod rwlock;
3
4use core::marker::PhantomData;
5use core::sync::atomic::AtomicU32;
6use core::sync::atomic::Ordering::Relaxed;
7use rusl::error::Errno;
8use rusl::futex::futex_wait;
9use rusl::platform::FutexFlags;
10pub use {mutex::Mutex, mutex::MutexGuard};
11pub use {rwlock::RwLock, rwlock::RwLockReadGuard, rwlock::RwLockWriteGuard};
12
13pub(crate) struct NotSend(PhantomData<*const ()>);
14
15impl NotSend {
16 #[inline]
17 const fn new() -> Self {
18 Self(PhantomData)
19 }
20}
21
22unsafe impl Sync for NotSend {}
23
24#[inline]
25pub(crate) fn futex_wait_fast(futex: &AtomicU32, expect: u32) {
26 loop {
27 if futex.load(Relaxed) != expect {
28 return;
29 }
30 match futex_wait(futex, expect, FutexFlags::PRIVATE, None) {
31 Ok(()) => {
32 return;
33 }
34 Err(e) => {
35 if let Some(code) = e.code {
36 if code == Errno::EINTR {
37 } else {
38 return;
39 }
40 }
41 }
42 }
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use crate::sync::futex_wait_fast;
49 use core::sync::atomic::AtomicU32;
50 use rusl::futex::futex_wake;
51
52 #[test]
53 fn wait_fast_shortcircuit() {
54 let futex = AtomicU32::new(0);
55 futex_wait_fast(&futex, 1);
57 }
58
59 #[test]
60 fn wait_fast_cant_short() {
61 let futex = std::sync::Arc::new(AtomicU32::new(0));
62 let f_c = futex.clone();
63 let handle = std::thread::spawn(move || {
64 futex_wait_fast(&f_c, 0);
65 });
66 while futex_wake(&futex, 1).unwrap() == 0 {}
68 handle.join().unwrap();
69 }
70}