wasmer_wasix/utils/
thread_parker.rs

1use std::{
2    sync::{Arc, Condvar, Mutex},
3    task::Waker,
4    time::Duration,
5};
6
7/// Represents a waker that can be used to put a thread to
8/// sleep while it waits for an event to occur
9#[derive(Debug)]
10pub struct WasiParkingLot {
11    waker: Waker,
12    #[allow(dead_code)]
13    run: Arc<(Mutex<bool>, Condvar)>,
14}
15
16impl Default for WasiParkingLot {
17    fn default() -> Self {
18        Self::new(true)
19    }
20}
21
22impl WasiParkingLot {
23    /// Creates a new parking lot with a specific value
24    pub fn new(initial_val: bool) -> Self {
25        let run = Arc::new((Mutex::new(initial_val), Condvar::default()));
26        let waker = {
27            let run = run.clone();
28            waker_fn::waker_fn(move || {
29                let mut guard = run.0.lock().unwrap();
30                *guard = true;
31                run.1.notify_one();
32            })
33        };
34
35        Self { waker, run }
36    }
37
38    /// Gets a reference to the waker that can be used for
39    /// asynchronous calls
40    pub fn get_waker(&self) -> Waker {
41        self.waker.clone()
42    }
43
44    /// Wakes one of the reactors thats currently waiting
45    pub fn wake(&self) {
46        self.waker.wake_by_ref();
47    }
48
49    /// Will wait until either the reactor is triggered
50    /// or the timeout occurs
51    // TODO: review allow...
52    #[allow(dead_code)]
53    pub fn wait(&self, timeout: Duration) -> bool {
54        let mut run = self.run.0.lock().unwrap();
55        if *run {
56            *run = false;
57            return true;
58        }
59        loop {
60            let woken = self.run.1.wait_timeout(run, timeout).unwrap();
61            if woken.1.timed_out() {
62                return false;
63            }
64            run = woken.0;
65            if *run {
66                *run = false;
67                return true;
68            }
69        }
70    }
71}