#![deny(warnings)] #[macro_use] extern crate futures; #[macro_use] extern crate loom; #[path = "../src/semaphore.rs"] #[allow(warnings)] mod semaphore; use semaphore::*; use futures::{future, Async, Future, Poll}; use loom::futures::block_on; use loom::thread; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering::SeqCst; use std::sync::Arc; #[test] fn basic_usage() { const NUM: usize = 2; struct Actor { waiter: Permit, shared: Arc, } struct Shared { semaphore: Semaphore, active: AtomicUsize, } impl Future for Actor { type Item = (); type Error = (); fn poll(&mut self) -> Poll<(), ()> { try_ready!(self .waiter .poll_acquire(&self.shared.semaphore) .map_err(|_| ())); let actual = self.shared.active.fetch_add(1, SeqCst); assert!(actual <= NUM - 1); let actual = self.shared.active.fetch_sub(1, SeqCst); assert!(actual <= NUM); self.waiter.release(&self.shared.semaphore); Ok(Async::Ready(())) } } loom::fuzz(|| { let shared = Arc::new(Shared { semaphore: Semaphore::new(NUM), active: AtomicUsize::new(0), }); for _ in 0..NUM { let shared = shared.clone(); thread::spawn(move || { block_on(Actor { waiter: Permit::new(), shared, }) .unwrap(); }); } block_on(Actor { waiter: Permit::new(), shared, }) .unwrap(); }); } #[test] fn release() { loom::fuzz(|| { let semaphore = Arc::new(Semaphore::new(1)); { let semaphore = semaphore.clone(); thread::spawn(move || { let mut permit = Permit::new(); block_on(future::lazy(|| { permit.poll_acquire(&semaphore).unwrap(); Ok::<_, ()>(()) })) .unwrap(); permit.release(&semaphore); }); } let mut permit = Permit::new(); block_on(future::poll_fn(|| permit.poll_acquire(&semaphore))).unwrap(); permit.release(&semaphore); }); } #[test] fn basic_closing() { const NUM: usize = 2; loom::fuzz(|| { let semaphore = Arc::new(Semaphore::new(1)); for _ in 0..NUM { let semaphore = semaphore.clone(); thread::spawn(move || { let mut permit = Permit::new(); for _ in 0..2 { block_on(future::poll_fn(|| { permit.poll_acquire(&semaphore).map_err(|_| ()) }))?; permit.release(&semaphore); } Ok::<(), ()>(()) }); } semaphore.close(); }); } #[test] fn concurrent_close() { const NUM: usize = 3; loom::fuzz(|| { let semaphore = Arc::new(Semaphore::new(1)); for _ in 0..NUM { let semaphore = semaphore.clone(); thread::spawn(move || { let mut permit = Permit::new(); block_on(future::poll_fn(|| { permit.poll_acquire(&semaphore).map_err(|_| ()) }))?; permit.release(&semaphore); semaphore.close(); Ok::<(), ()>(()) }); } }); }