#[cfg(not(target_family = "wasm"))]
mod example {
#![allow(dead_code)]
use std::cell::UnsafeCell;
use std::ops::{Deref, DerefMut};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{mpsc, Arc};
use std::thread;
use std::time::{Duration, Instant};
use event_listener::Event;
struct Mutex<T> {
locked: AtomicBool,
lock_ops: Event,
data: UnsafeCell<T>,
}
unsafe impl<T: Send> Send for Mutex<T> {}
unsafe impl<T: Send> Sync for Mutex<T> {}
impl<T> Mutex<T> {
fn new(t: T) -> Mutex<T> {
Mutex {
locked: AtomicBool::new(false),
lock_ops: Event::new(),
data: UnsafeCell::new(t),
}
}
fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
if !self.locked.swap(true, Ordering::Acquire) {
Some(MutexGuard(self))
} else {
None
}
}
fn lock(&self) -> MutexGuard<'_, T> {
let mut listener = None;
loop {
if let Some(guard) = self.try_lock() {
return guard;
}
match listener.take() {
None => {
listener = Some(self.lock_ops.listen());
}
Some(mut l) => {
l.as_mut().wait();
}
}
}
}
fn lock_timeout(&self, timeout: Duration) -> Option<MutexGuard<'_, T>> {
let deadline = Instant::now() + timeout;
let mut listener = None;
loop {
if let Some(guard) = self.try_lock() {
return Some(guard);
}
match listener.take() {
None => {
listener = Some(self.lock_ops.listen());
}
Some(mut l) => {
l.as_mut().wait_deadline(deadline)?;
}
}
}
}
async fn lock_async(&self) -> MutexGuard<'_, T> {
let mut listener = None;
loop {
if let Some(guard) = self.try_lock() {
return guard;
}
match listener.take() {
None => {
listener = Some(self.lock_ops.listen());
}
Some(l) => {
l.await;
}
}
}
}
}
struct MutexGuard<'a, T>(&'a Mutex<T>);
unsafe impl<T: Send> Send for MutexGuard<'_, T> {}
unsafe impl<T: Sync> Sync for MutexGuard<'_, T> {}
impl<T> Drop for MutexGuard<'_, T> {
fn drop(&mut self) {
self.0.locked.store(false, Ordering::Release);
self.0.lock_ops.notify(1);
}
}
impl<T> Deref for MutexGuard<'_, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.0.data.get() }
}
}
impl<T> DerefMut for MutexGuard<'_, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.0.data.get() }
}
}
pub(super) fn entry() {
const N: usize = 10;
let counter = Arc::new(Mutex::new(0));
let (tx, rx) = mpsc::channel();
for _ in 0..N {
let counter = counter.clone();
let tx = tx.clone();
thread::spawn(move || {
let mut counter = counter.lock();
*counter += 1;
if *counter == N {
tx.send(()).unwrap();
}
});
}
rx.recv().unwrap();
assert_eq!(*counter.lock(), N);
println!("Done!");
}
}
#[cfg(target_family = "wasm")]
mod example {
pub(super) fn entry() {
println!("This example is not supported on wasm yet.");
}
}
fn main() {
example::entry();
}