1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker use std::cell::UnsafeCell; 6*bb4ee6a4SAndroid Build Coastguard Worker use std::future::Future; 7*bb4ee6a4SAndroid Build Coastguard Worker use std::mem; 8*bb4ee6a4SAndroid Build Coastguard Worker use std::pin::Pin; 9*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr::NonNull; 10*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::AtomicBool; 11*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::AtomicU8; 12*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::Ordering; 13*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc; 14*bb4ee6a4SAndroid Build Coastguard Worker use std::task::Context; 15*bb4ee6a4SAndroid Build Coastguard Worker use std::task::Poll; 16*bb4ee6a4SAndroid Build Coastguard Worker use std::task::Waker; 17*bb4ee6a4SAndroid Build Coastguard Worker 18*bb4ee6a4SAndroid Build Coastguard Worker use intrusive_collections::intrusive_adapter; 19*bb4ee6a4SAndroid Build Coastguard Worker use intrusive_collections::linked_list::LinkedList; 20*bb4ee6a4SAndroid Build Coastguard Worker use intrusive_collections::linked_list::LinkedListOps; 21*bb4ee6a4SAndroid Build Coastguard Worker use intrusive_collections::DefaultLinkOps; 22*bb4ee6a4SAndroid Build Coastguard Worker use intrusive_collections::LinkOps; 23*bb4ee6a4SAndroid Build Coastguard Worker 24*bb4ee6a4SAndroid Build Coastguard Worker use super::super::sync::SpinLock; 25*bb4ee6a4SAndroid Build Coastguard Worker 26*bb4ee6a4SAndroid Build Coastguard Worker // An atomic version of a LinkedListLink. See https://github.com/Amanieu/intrusive-rs/issues/47 for 27*bb4ee6a4SAndroid Build Coastguard Worker // more details. 28*bb4ee6a4SAndroid Build Coastguard Worker #[repr(align(128))] 29*bb4ee6a4SAndroid Build Coastguard Worker pub struct AtomicLink { 30*bb4ee6a4SAndroid Build Coastguard Worker prev: UnsafeCell<Option<NonNull<AtomicLink>>>, 31*bb4ee6a4SAndroid Build Coastguard Worker next: UnsafeCell<Option<NonNull<AtomicLink>>>, 32*bb4ee6a4SAndroid Build Coastguard Worker linked: AtomicBool, 33*bb4ee6a4SAndroid Build Coastguard Worker } 34*bb4ee6a4SAndroid Build Coastguard Worker 35*bb4ee6a4SAndroid Build Coastguard Worker impl AtomicLink { new() -> AtomicLink36*bb4ee6a4SAndroid Build Coastguard Worker fn new() -> AtomicLink { 37*bb4ee6a4SAndroid Build Coastguard Worker AtomicLink { 38*bb4ee6a4SAndroid Build Coastguard Worker linked: AtomicBool::new(false), 39*bb4ee6a4SAndroid Build Coastguard Worker prev: UnsafeCell::new(None), 40*bb4ee6a4SAndroid Build Coastguard Worker next: UnsafeCell::new(None), 41*bb4ee6a4SAndroid Build Coastguard Worker } 42*bb4ee6a4SAndroid Build Coastguard Worker } 43*bb4ee6a4SAndroid Build Coastguard Worker is_linked(&self) -> bool44*bb4ee6a4SAndroid Build Coastguard Worker fn is_linked(&self) -> bool { 45*bb4ee6a4SAndroid Build Coastguard Worker self.linked.load(Ordering::Relaxed) 46*bb4ee6a4SAndroid Build Coastguard Worker } 47*bb4ee6a4SAndroid Build Coastguard Worker } 48*bb4ee6a4SAndroid Build Coastguard Worker 49*bb4ee6a4SAndroid Build Coastguard Worker impl DefaultLinkOps for AtomicLink { 50*bb4ee6a4SAndroid Build Coastguard Worker type Ops = AtomicLinkOps; 51*bb4ee6a4SAndroid Build Coastguard Worker 52*bb4ee6a4SAndroid Build Coastguard Worker const NEW: Self::Ops = AtomicLinkOps; 53*bb4ee6a4SAndroid Build Coastguard Worker } 54*bb4ee6a4SAndroid Build Coastguard Worker 55*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 56*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the only way to mutate `AtomicLink` is via the `LinkedListOps` trait whose methods 57*bb4ee6a4SAndroid Build Coastguard Worker // are all unsafe and require that the caller has first called `acquire_link` (and had it return 58*bb4ee6a4SAndroid Build Coastguard Worker // true) to use them safely. 59*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Send for AtomicLink {} 60*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: See safety comment for impl Send 61*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Sync for AtomicLink {} 62*bb4ee6a4SAndroid Build Coastguard Worker 63*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Default)] 64*bb4ee6a4SAndroid Build Coastguard Worker pub struct AtomicLinkOps; 65*bb4ee6a4SAndroid Build Coastguard Worker 66*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/315998194): Add safety comment 67*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)] 68*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl LinkOps for AtomicLinkOps { 69*bb4ee6a4SAndroid Build Coastguard Worker type LinkPtr = NonNull<AtomicLink>; 70*bb4ee6a4SAndroid Build Coastguard Worker acquire_link(&mut self, ptr: Self::LinkPtr) -> bool71*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn acquire_link(&mut self, ptr: Self::LinkPtr) -> bool { 72*bb4ee6a4SAndroid Build Coastguard Worker !ptr.as_ref().linked.swap(true, Ordering::Acquire) 73*bb4ee6a4SAndroid Build Coastguard Worker } 74*bb4ee6a4SAndroid Build Coastguard Worker release_link(&mut self, ptr: Self::LinkPtr)75*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn release_link(&mut self, ptr: Self::LinkPtr) { 76*bb4ee6a4SAndroid Build Coastguard Worker ptr.as_ref().linked.store(false, Ordering::Release) 77*bb4ee6a4SAndroid Build Coastguard Worker } 78*bb4ee6a4SAndroid Build Coastguard Worker } 79*bb4ee6a4SAndroid Build Coastguard Worker 80*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/315998194): Add safety comment 81*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)] 82*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl LinkedListOps for AtomicLinkOps { next(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr>83*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn next(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr> { 84*bb4ee6a4SAndroid Build Coastguard Worker *ptr.as_ref().next.get() 85*bb4ee6a4SAndroid Build Coastguard Worker } 86*bb4ee6a4SAndroid Build Coastguard Worker prev(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr>87*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn prev(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr> { 88*bb4ee6a4SAndroid Build Coastguard Worker *ptr.as_ref().prev.get() 89*bb4ee6a4SAndroid Build Coastguard Worker } 90*bb4ee6a4SAndroid Build Coastguard Worker set_next(&mut self, ptr: Self::LinkPtr, next: Option<Self::LinkPtr>)91*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option<Self::LinkPtr>) { 92*bb4ee6a4SAndroid Build Coastguard Worker *ptr.as_ref().next.get() = next; 93*bb4ee6a4SAndroid Build Coastguard Worker } 94*bb4ee6a4SAndroid Build Coastguard Worker set_prev(&mut self, ptr: Self::LinkPtr, prev: Option<Self::LinkPtr>)95*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn set_prev(&mut self, ptr: Self::LinkPtr, prev: Option<Self::LinkPtr>) { 96*bb4ee6a4SAndroid Build Coastguard Worker *ptr.as_ref().prev.get() = prev; 97*bb4ee6a4SAndroid Build Coastguard Worker } 98*bb4ee6a4SAndroid Build Coastguard Worker } 99*bb4ee6a4SAndroid Build Coastguard Worker 100*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy)] 101*bb4ee6a4SAndroid Build Coastguard Worker pub enum Kind { 102*bb4ee6a4SAndroid Build Coastguard Worker Shared, 103*bb4ee6a4SAndroid Build Coastguard Worker Exclusive, 104*bb4ee6a4SAndroid Build Coastguard Worker } 105*bb4ee6a4SAndroid Build Coastguard Worker 106*bb4ee6a4SAndroid Build Coastguard Worker enum State { 107*bb4ee6a4SAndroid Build Coastguard Worker Init, 108*bb4ee6a4SAndroid Build Coastguard Worker Waiting(Waker), 109*bb4ee6a4SAndroid Build Coastguard Worker Woken, 110*bb4ee6a4SAndroid Build Coastguard Worker Finished, 111*bb4ee6a4SAndroid Build Coastguard Worker Processing, 112*bb4ee6a4SAndroid Build Coastguard Worker } 113*bb4ee6a4SAndroid Build Coastguard Worker 114*bb4ee6a4SAndroid Build Coastguard Worker // Indicates the queue to which the waiter belongs. It is the responsibility of the Mutex and 115*bb4ee6a4SAndroid Build Coastguard Worker // Condvar implementations to update this value when adding/removing a Waiter from their respective 116*bb4ee6a4SAndroid Build Coastguard Worker // waiter lists. 117*bb4ee6a4SAndroid Build Coastguard Worker #[repr(u8)] 118*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Eq, PartialEq)] 119*bb4ee6a4SAndroid Build Coastguard Worker pub enum WaitingFor { 120*bb4ee6a4SAndroid Build Coastguard Worker // The waiter is either not linked into a waiter list or it is linked into a temporary list. 121*bb4ee6a4SAndroid Build Coastguard Worker None = 0, 122*bb4ee6a4SAndroid Build Coastguard Worker // The waiter is linked into the Mutex's waiter list. 123*bb4ee6a4SAndroid Build Coastguard Worker Mutex = 1, 124*bb4ee6a4SAndroid Build Coastguard Worker // The waiter is linked into the Condvar's waiter list. 125*bb4ee6a4SAndroid Build Coastguard Worker Condvar = 2, 126*bb4ee6a4SAndroid Build Coastguard Worker } 127*bb4ee6a4SAndroid Build Coastguard Worker 128*bb4ee6a4SAndroid Build Coastguard Worker // Represents a thread currently blocked on a Condvar or on acquiring a Mutex. 129*bb4ee6a4SAndroid Build Coastguard Worker pub struct Waiter { 130*bb4ee6a4SAndroid Build Coastguard Worker link: AtomicLink, 131*bb4ee6a4SAndroid Build Coastguard Worker state: SpinLock<State>, 132*bb4ee6a4SAndroid Build Coastguard Worker cancel: fn(usize, &Waiter, bool), 133*bb4ee6a4SAndroid Build Coastguard Worker cancel_data: usize, 134*bb4ee6a4SAndroid Build Coastguard Worker kind: Kind, 135*bb4ee6a4SAndroid Build Coastguard Worker waiting_for: AtomicU8, 136*bb4ee6a4SAndroid Build Coastguard Worker } 137*bb4ee6a4SAndroid Build Coastguard Worker 138*bb4ee6a4SAndroid Build Coastguard Worker impl Waiter { 139*bb4ee6a4SAndroid Build Coastguard Worker // Create a new, initialized Waiter. 140*bb4ee6a4SAndroid Build Coastguard Worker // 141*bb4ee6a4SAndroid Build Coastguard Worker // `kind` should indicate whether this waiter represent a thread that is waiting for a shared 142*bb4ee6a4SAndroid Build Coastguard Worker // lock or an exclusive lock. 143*bb4ee6a4SAndroid Build Coastguard Worker // 144*bb4ee6a4SAndroid Build Coastguard Worker // `cancel` is the function that is called when a `WaitFuture` (returned by the `wait()` 145*bb4ee6a4SAndroid Build Coastguard Worker // function) is dropped before it can complete. `cancel_data` is used as the first parameter of 146*bb4ee6a4SAndroid Build Coastguard Worker // the `cancel` function. The second parameter is the `Waiter` that was canceled and the third 147*bb4ee6a4SAndroid Build Coastguard Worker // parameter indicates whether the `WaitFuture` was dropped after it was woken (but before it 148*bb4ee6a4SAndroid Build Coastguard Worker // was polled to completion). A value of `false` for the third parameter may already be stale 149*bb4ee6a4SAndroid Build Coastguard Worker // by the time the cancel function runs and so does not guarantee that the waiter was not woken. 150*bb4ee6a4SAndroid Build Coastguard Worker // In this case, implementations should still check if the Waiter was woken. However, a value of 151*bb4ee6a4SAndroid Build Coastguard Worker // `true` guarantees that the waiter was already woken up so no additional checks are necessary. 152*bb4ee6a4SAndroid Build Coastguard Worker // In this case, the cancel implementation should wake up the next waiter in its wait list, if 153*bb4ee6a4SAndroid Build Coastguard Worker // any. 154*bb4ee6a4SAndroid Build Coastguard Worker // 155*bb4ee6a4SAndroid Build Coastguard Worker // `waiting_for` indicates the waiter list to which this `Waiter` will be added. See the 156*bb4ee6a4SAndroid Build Coastguard Worker // documentation of the `WaitingFor` enum for the meaning of the different values. new( kind: Kind, cancel: fn(usize, &Waiter, bool), cancel_data: usize, waiting_for: WaitingFor, ) -> Waiter157*bb4ee6a4SAndroid Build Coastguard Worker pub fn new( 158*bb4ee6a4SAndroid Build Coastguard Worker kind: Kind, 159*bb4ee6a4SAndroid Build Coastguard Worker cancel: fn(usize, &Waiter, bool), 160*bb4ee6a4SAndroid Build Coastguard Worker cancel_data: usize, 161*bb4ee6a4SAndroid Build Coastguard Worker waiting_for: WaitingFor, 162*bb4ee6a4SAndroid Build Coastguard Worker ) -> Waiter { 163*bb4ee6a4SAndroid Build Coastguard Worker Waiter { 164*bb4ee6a4SAndroid Build Coastguard Worker link: AtomicLink::new(), 165*bb4ee6a4SAndroid Build Coastguard Worker state: SpinLock::new(State::Init), 166*bb4ee6a4SAndroid Build Coastguard Worker cancel, 167*bb4ee6a4SAndroid Build Coastguard Worker cancel_data, 168*bb4ee6a4SAndroid Build Coastguard Worker kind, 169*bb4ee6a4SAndroid Build Coastguard Worker waiting_for: AtomicU8::new(waiting_for as u8), 170*bb4ee6a4SAndroid Build Coastguard Worker } 171*bb4ee6a4SAndroid Build Coastguard Worker } 172*bb4ee6a4SAndroid Build Coastguard Worker 173*bb4ee6a4SAndroid Build Coastguard Worker // The kind of lock that this `Waiter` is waiting to acquire. kind(&self) -> Kind174*bb4ee6a4SAndroid Build Coastguard Worker pub fn kind(&self) -> Kind { 175*bb4ee6a4SAndroid Build Coastguard Worker self.kind 176*bb4ee6a4SAndroid Build Coastguard Worker } 177*bb4ee6a4SAndroid Build Coastguard Worker 178*bb4ee6a4SAndroid Build Coastguard Worker // Returns true if this `Waiter` is currently linked into a waiter list. is_linked(&self) -> bool179*bb4ee6a4SAndroid Build Coastguard Worker pub fn is_linked(&self) -> bool { 180*bb4ee6a4SAndroid Build Coastguard Worker self.link.is_linked() 181*bb4ee6a4SAndroid Build Coastguard Worker } 182*bb4ee6a4SAndroid Build Coastguard Worker 183*bb4ee6a4SAndroid Build Coastguard Worker // Indicates the waiter list to which this `Waiter` belongs. is_waiting_for(&self) -> WaitingFor184*bb4ee6a4SAndroid Build Coastguard Worker pub fn is_waiting_for(&self) -> WaitingFor { 185*bb4ee6a4SAndroid Build Coastguard Worker match self.waiting_for.load(Ordering::Acquire) { 186*bb4ee6a4SAndroid Build Coastguard Worker 0 => WaitingFor::None, 187*bb4ee6a4SAndroid Build Coastguard Worker 1 => WaitingFor::Mutex, 188*bb4ee6a4SAndroid Build Coastguard Worker 2 => WaitingFor::Condvar, 189*bb4ee6a4SAndroid Build Coastguard Worker v => panic!("Unknown value for `WaitingFor`: {}", v), 190*bb4ee6a4SAndroid Build Coastguard Worker } 191*bb4ee6a4SAndroid Build Coastguard Worker } 192*bb4ee6a4SAndroid Build Coastguard Worker 193*bb4ee6a4SAndroid Build Coastguard Worker // Change the waiter list to which this `Waiter` belongs. This will panic if called when the 194*bb4ee6a4SAndroid Build Coastguard Worker // `Waiter` is still linked into a waiter list. set_waiting_for(&self, waiting_for: WaitingFor)195*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_waiting_for(&self, waiting_for: WaitingFor) { 196*bb4ee6a4SAndroid Build Coastguard Worker self.waiting_for.store(waiting_for as u8, Ordering::Release); 197*bb4ee6a4SAndroid Build Coastguard Worker } 198*bb4ee6a4SAndroid Build Coastguard Worker 199*bb4ee6a4SAndroid Build Coastguard Worker // Reset the Waiter back to its initial state. Panics if this `Waiter` is still linked into a 200*bb4ee6a4SAndroid Build Coastguard Worker // waiter list. reset(&self, waiting_for: WaitingFor)201*bb4ee6a4SAndroid Build Coastguard Worker pub fn reset(&self, waiting_for: WaitingFor) { 202*bb4ee6a4SAndroid Build Coastguard Worker debug_assert!(!self.is_linked(), "Cannot reset `Waiter` while linked"); 203*bb4ee6a4SAndroid Build Coastguard Worker self.set_waiting_for(waiting_for); 204*bb4ee6a4SAndroid Build Coastguard Worker 205*bb4ee6a4SAndroid Build Coastguard Worker let mut state = self.state.lock(); 206*bb4ee6a4SAndroid Build Coastguard Worker if let State::Waiting(waker) = mem::replace(&mut *state, State::Init) { 207*bb4ee6a4SAndroid Build Coastguard Worker mem::drop(state); 208*bb4ee6a4SAndroid Build Coastguard Worker mem::drop(waker); 209*bb4ee6a4SAndroid Build Coastguard Worker } 210*bb4ee6a4SAndroid Build Coastguard Worker } 211*bb4ee6a4SAndroid Build Coastguard Worker 212*bb4ee6a4SAndroid Build Coastguard Worker // Wait until woken up by another thread. wait(&self) -> WaitFuture<'_>213*bb4ee6a4SAndroid Build Coastguard Worker pub fn wait(&self) -> WaitFuture<'_> { 214*bb4ee6a4SAndroid Build Coastguard Worker WaitFuture { waiter: self } 215*bb4ee6a4SAndroid Build Coastguard Worker } 216*bb4ee6a4SAndroid Build Coastguard Worker 217*bb4ee6a4SAndroid Build Coastguard Worker // Wake up the thread associated with this `Waiter`. Panics if `waiting_for()` does not return 218*bb4ee6a4SAndroid Build Coastguard Worker // `WaitingFor::None` or if `is_linked()` returns true. wake(&self)219*bb4ee6a4SAndroid Build Coastguard Worker pub fn wake(&self) { 220*bb4ee6a4SAndroid Build Coastguard Worker debug_assert!(!self.is_linked(), "Cannot wake `Waiter` while linked"); 221*bb4ee6a4SAndroid Build Coastguard Worker debug_assert_eq!(self.is_waiting_for(), WaitingFor::None); 222*bb4ee6a4SAndroid Build Coastguard Worker 223*bb4ee6a4SAndroid Build Coastguard Worker let mut state = self.state.lock(); 224*bb4ee6a4SAndroid Build Coastguard Worker 225*bb4ee6a4SAndroid Build Coastguard Worker if let State::Waiting(waker) = mem::replace(&mut *state, State::Woken) { 226*bb4ee6a4SAndroid Build Coastguard Worker mem::drop(state); 227*bb4ee6a4SAndroid Build Coastguard Worker waker.wake(); 228*bb4ee6a4SAndroid Build Coastguard Worker } 229*bb4ee6a4SAndroid Build Coastguard Worker } 230*bb4ee6a4SAndroid Build Coastguard Worker } 231*bb4ee6a4SAndroid Build Coastguard Worker 232*bb4ee6a4SAndroid Build Coastguard Worker pub struct WaitFuture<'w> { 233*bb4ee6a4SAndroid Build Coastguard Worker waiter: &'w Waiter, 234*bb4ee6a4SAndroid Build Coastguard Worker } 235*bb4ee6a4SAndroid Build Coastguard Worker 236*bb4ee6a4SAndroid Build Coastguard Worker impl<'w> Future for WaitFuture<'w> { 237*bb4ee6a4SAndroid Build Coastguard Worker type Output = (); 238*bb4ee6a4SAndroid Build Coastguard Worker poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output>239*bb4ee6a4SAndroid Build Coastguard Worker fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { 240*bb4ee6a4SAndroid Build Coastguard Worker let mut state = self.waiter.state.lock(); 241*bb4ee6a4SAndroid Build Coastguard Worker 242*bb4ee6a4SAndroid Build Coastguard Worker match mem::replace(&mut *state, State::Processing) { 243*bb4ee6a4SAndroid Build Coastguard Worker State::Init => { 244*bb4ee6a4SAndroid Build Coastguard Worker *state = State::Waiting(cx.waker().clone()); 245*bb4ee6a4SAndroid Build Coastguard Worker 246*bb4ee6a4SAndroid Build Coastguard Worker Poll::Pending 247*bb4ee6a4SAndroid Build Coastguard Worker } 248*bb4ee6a4SAndroid Build Coastguard Worker State::Waiting(old_waker) => { 249*bb4ee6a4SAndroid Build Coastguard Worker *state = State::Waiting(cx.waker().clone()); 250*bb4ee6a4SAndroid Build Coastguard Worker mem::drop(state); 251*bb4ee6a4SAndroid Build Coastguard Worker mem::drop(old_waker); 252*bb4ee6a4SAndroid Build Coastguard Worker 253*bb4ee6a4SAndroid Build Coastguard Worker Poll::Pending 254*bb4ee6a4SAndroid Build Coastguard Worker } 255*bb4ee6a4SAndroid Build Coastguard Worker State::Woken => { 256*bb4ee6a4SAndroid Build Coastguard Worker *state = State::Finished; 257*bb4ee6a4SAndroid Build Coastguard Worker Poll::Ready(()) 258*bb4ee6a4SAndroid Build Coastguard Worker } 259*bb4ee6a4SAndroid Build Coastguard Worker State::Finished => { 260*bb4ee6a4SAndroid Build Coastguard Worker panic!("Future polled after returning Poll::Ready"); 261*bb4ee6a4SAndroid Build Coastguard Worker } 262*bb4ee6a4SAndroid Build Coastguard Worker State::Processing => { 263*bb4ee6a4SAndroid Build Coastguard Worker panic!("Unexpected waker state"); 264*bb4ee6a4SAndroid Build Coastguard Worker } 265*bb4ee6a4SAndroid Build Coastguard Worker } 266*bb4ee6a4SAndroid Build Coastguard Worker } 267*bb4ee6a4SAndroid Build Coastguard Worker } 268*bb4ee6a4SAndroid Build Coastguard Worker 269*bb4ee6a4SAndroid Build Coastguard Worker impl<'w> Drop for WaitFuture<'w> { drop(&mut self)270*bb4ee6a4SAndroid Build Coastguard Worker fn drop(&mut self) { 271*bb4ee6a4SAndroid Build Coastguard Worker let state = self.waiter.state.lock(); 272*bb4ee6a4SAndroid Build Coastguard Worker 273*bb4ee6a4SAndroid Build Coastguard Worker match *state { 274*bb4ee6a4SAndroid Build Coastguard Worker State::Finished => {} 275*bb4ee6a4SAndroid Build Coastguard Worker State::Processing => panic!("Unexpected waker state"), 276*bb4ee6a4SAndroid Build Coastguard Worker State::Woken => { 277*bb4ee6a4SAndroid Build Coastguard Worker mem::drop(state); 278*bb4ee6a4SAndroid Build Coastguard Worker 279*bb4ee6a4SAndroid Build Coastguard Worker // We were woken but not polled. Wake up the next waiter. 280*bb4ee6a4SAndroid Build Coastguard Worker (self.waiter.cancel)(self.waiter.cancel_data, self.waiter, true); 281*bb4ee6a4SAndroid Build Coastguard Worker } 282*bb4ee6a4SAndroid Build Coastguard Worker _ => { 283*bb4ee6a4SAndroid Build Coastguard Worker mem::drop(state); 284*bb4ee6a4SAndroid Build Coastguard Worker 285*bb4ee6a4SAndroid Build Coastguard Worker // Not woken. No need to wake up any waiters. 286*bb4ee6a4SAndroid Build Coastguard Worker (self.waiter.cancel)(self.waiter.cancel_data, self.waiter, false); 287*bb4ee6a4SAndroid Build Coastguard Worker } 288*bb4ee6a4SAndroid Build Coastguard Worker } 289*bb4ee6a4SAndroid Build Coastguard Worker } 290*bb4ee6a4SAndroid Build Coastguard Worker } 291*bb4ee6a4SAndroid Build Coastguard Worker 292*bb4ee6a4SAndroid Build Coastguard Worker intrusive_adapter!(pub WaiterAdapter = Arc<Waiter>: Waiter { link: AtomicLink }); 293*bb4ee6a4SAndroid Build Coastguard Worker 294*bb4ee6a4SAndroid Build Coastguard Worker pub type WaiterList = LinkedList<WaiterAdapter>; 295