polars_async/primitives/
task_parker.rs1use std::future::Future;
2use std::pin::Pin;
3use std::sync::atomic::{AtomicU8, Ordering};
4use std::task::{Context, Poll, Waker};
5
6use parking_lot::Mutex;
7
8#[derive(Default)]
9pub struct TaskParker {
10 state: AtomicU8,
11 waker: Mutex<Option<Waker>>,
12}
13
14impl TaskParker {
15 const RUNNING: u8 = 0;
16 const PREPARING_TO_PARK: u8 = 1;
17 const PARKED: u8 = 2;
18
19 pub fn park(&self) -> TaskParkFuture<'_> {
24 self.state.store(Self::PREPARING_TO_PARK, Ordering::SeqCst);
25 TaskParkFuture { parker: self }
26 }
27
28 pub fn unpark(&self) {
30 let state = self.state.load(Ordering::SeqCst);
31 if state != Self::RUNNING {
32 let old_state = self.state.swap(Self::RUNNING, Ordering::SeqCst);
33 if old_state == Self::PARKED {
34 if let Some(w) = self.waker.lock().take() {
35 w.wake();
36 }
37 }
38 }
39 }
40}
41
42pub struct TaskParkFuture<'a> {
43 parker: &'a TaskParker,
44}
45
46impl Future for TaskParkFuture<'_> {
47 type Output = ();
48
49 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
50 let mut state = self.parker.state.load(Ordering::SeqCst);
51 loop {
52 match state {
53 TaskParker::RUNNING => return Poll::Ready(()),
54
55 TaskParker::PARKED => {
56 match &mut *self.parker.waker.lock() {
58 Some(w) => w.clone_from(cx.waker()),
59 None => return Poll::Ready(()), }
61 },
62 TaskParker::PREPARING_TO_PARK => {
63 *self.parker.waker.lock() = Some(cx.waker().clone());
66 match self.parker.state.compare_exchange_weak(
67 TaskParker::PREPARING_TO_PARK,
68 TaskParker::PARKED,
69 Ordering::SeqCst,
70 Ordering::SeqCst,
71 ) {
72 Ok(_) => return Poll::Pending,
73 Err(s) => state = s,
74 }
75 },
76 _ => unreachable!(),
77 }
78 }
79 }
80}