#![feature(test)] extern crate futures; extern crate test; use futures::{Async, Poll}; use futures::executor; use futures::executor::{Notify, NotifyHandle}; use futures::sync::BiLock; use futures::sync::BiLockAcquire; use futures::sync::BiLockAcquired; use futures::future::Future; use futures::stream::Stream; use test::Bencher; fn notify_noop() -> NotifyHandle { struct Noop; impl Notify for Noop { fn notify(&self, _id: usize) {} } const NOOP : &'static Noop = &Noop; NotifyHandle::from(NOOP) } /// Pseudo-stream which simply calls `lock.poll()` on `poll` struct LockStream { lock: BiLockAcquire, } impl LockStream { fn new(lock: BiLock) -> LockStream { LockStream { lock: lock.lock() } } /// Release a lock after it was acquired in `poll`, /// so `poll` could be called again. fn release_lock(&mut self, guard: BiLockAcquired) { self.lock = guard.unlock().lock() } } impl Stream for LockStream { type Item = BiLockAcquired; type Error = (); fn poll(&mut self) -> Poll, Self::Error> { self.lock.poll().map(|a| match a { Async::Ready(a) => Async::Ready(Some(a)), Async::NotReady => Async::NotReady, }) } } #[bench] fn contended(b: &mut Bencher) { b.iter(|| { let (x, y) = BiLock::new(1); let mut x = executor::spawn(LockStream::new(x)); let mut y = executor::spawn(LockStream::new(y)); for _ in 0..1000 { let x_guard = match x.poll_stream_notify(¬ify_noop(), 11) { Ok(Async::Ready(Some(guard))) => guard, _ => panic!(), }; // Try poll second lock while first lock still holds the lock match y.poll_stream_notify(¬ify_noop(), 11) { Ok(Async::NotReady) => (), _ => panic!(), }; x.get_mut().release_lock(x_guard); let y_guard = match y.poll_stream_notify(¬ify_noop(), 11) { Ok(Async::Ready(Some(guard))) => guard, _ => panic!(), }; y.get_mut().release_lock(y_guard); } (x, y) }); } #[bench] fn lock_unlock(b: &mut Bencher) { b.iter(|| { let (x, y) = BiLock::new(1); let mut x = executor::spawn(LockStream::new(x)); let mut y = executor::spawn(LockStream::new(y)); for _ in 0..1000 { let x_guard = match x.poll_stream_notify(¬ify_noop(), 11) { Ok(Async::Ready(Some(guard))) => guard, _ => panic!(), }; x.get_mut().release_lock(x_guard); let y_guard = match y.poll_stream_notify(¬ify_noop(), 11) { Ok(Async::Ready(Some(guard))) => guard, _ => panic!(), }; y.get_mut().release_lock(y_guard); } (x, y) }) }