1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
use std::{
    future::Future,
    pin::Pin,
    task::{Context, Poll, Waker},
    time::Duration,
    collections::HashMap,
    rc::Rc,
    cell::RefCell,
};

type Listeners = HashMap<u32, Box<dyn Fn() + 'static>>;

static mut LISTENERS: Option<Listeners> = None;

fn get_free_listener_key() -> u32 {
    let listeners = get_listeners();
    for i in 0..u32::max_value() {
        if listeners.contains_key(&i) {
            continue;
        }

        return i;
    }

    return 0;
}

fn get_listeners() -> &'static mut Listeners {
    unsafe {
        if LISTENERS.is_none() {
            LISTENERS = Some(HashMap::new());
        }

        LISTENERS.as_mut().unwrap()
    }
}

fn insert_listener(listener_id: u32, callback: Box<dyn Fn() + 'static>) {
    let listeners = get_listeners();
    listeners.insert(listener_id, callback);
}

#[no_mangle]
fn trigger_timeout(listener_id: u32) {
    let wake = get_listeners().get(&listener_id).unwrap();
    wake();
}

#[no_mangle]
extern "C" {
    pub fn request_timeout(listener_id: u32, millis: u32);
}

pub struct TimerFuture {
    state: Rc<RefCell<State>>,
}

struct State {
    completed: bool,
    waker: Option<Waker>,
}

impl Future for TimerFuture {
    type Output = ();

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let mut state = self.state.borrow_mut();

        if state.completed {
            Poll::Ready(())
        } else {
            state.waker = Some(cx.waker().clone());
            Poll::Pending
        }
    }
}

unsafe impl Send for TimerFuture { }

impl TimerFuture {
    pub fn new(duration: Duration) -> Self {
        let listener_id = get_free_listener_key();
        let timer = TimerFuture {
            state: Rc::new(RefCell::new(State {
                completed: false,
                waker: None
            })),
        };

        let listener_state = timer.state.clone();

        insert_listener(listener_id, Box::new(move || {
            let mut state = listener_state.borrow_mut();
            state.completed = true;

            if let Some(waker) = state.waker.take() {
                std::mem::drop(state);
                waker.wake();
            }
        }));

        unsafe {
            request_timeout(listener_id, duration.as_millis() as u32);
        }

        timer
    }
}