blob: 7ee9f41fdb4d186edf2ffa15d88022d4b27523ae [file] [log] [blame]
#[cfg(all(feature = "alloc", feature = "std"))]
#[test]
fn mutex_acquire_uncontested() {
use futures::future::FutureExt;
use futures::lock::Mutex;
use futures_test::task::panic_context;
let mutex = Mutex::new(());
for _ in 0..10 {
assert!(mutex.lock().poll_unpin(&mut panic_context()).is_ready());
}
}
#[cfg(all(feature = "alloc", feature = "std"))]
#[test]
fn mutex_wakes_waiters() {
use futures::future::FutureExt;
use futures::lock::Mutex;
use futures::task::Context;
use futures_test::task::{new_count_waker, panic_context};
let mutex = Mutex::new(());
let (waker, counter) = new_count_waker();
let lock = mutex.lock().poll_unpin(&mut panic_context());
assert!(lock.is_ready());
let mut cx = Context::from_waker(&waker);
let mut waiter = mutex.lock();
assert!(waiter.poll_unpin(&mut cx).is_pending());
assert_eq!(counter, 0);
drop(lock);
assert_eq!(counter, 1);
assert!(waiter.poll_unpin(&mut panic_context()).is_ready());
}
#[cfg(feature = "thread-pool")]
#[test]
fn mutex_contested() {
use futures::channel::mpsc;
use futures::executor::block_on;
use futures::future::ready;
use futures::lock::Mutex;
use futures::stream::StreamExt;
use futures::task::SpawnExt;
use futures_test::future::FutureTestExt;
use std::sync::Arc;
let (tx, mut rx) = mpsc::unbounded();
let pool = futures::executor::ThreadPool::builder()
.pool_size(16)
.create()
.unwrap();
let tx = Arc::new(tx);
let mutex = Arc::new(Mutex::new(0));
let num_tasks = 1000;
for _ in 0..num_tasks {
let tx = tx.clone();
let mutex = mutex.clone();
pool.spawn(async move {
let mut lock = mutex.lock().await;
ready(()).pending_once().await;
*lock += 1;
tx.unbounded_send(()).unwrap();
drop(lock);
})
.unwrap();
}
block_on(async {
for _ in 0..num_tasks {
rx.next().await.unwrap();
}
let lock = mutex.lock().await;
assert_eq!(num_tasks, *lock);
})
}