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
pub mod queue;

use core::{future::Future, time::Duration};
use maitake::task::JoinHandle;
use spinning_top::Spinlock;

/// Poplar supports running asynchronous tasks (which we call *tasklets* to differentiate from
/// our userspace Task objects) in kernelspace through a [`maitake`](https://github.com/hawkw/mycelium/tree/main/maitake)-based
/// runtime.
pub struct TaskletScheduler {
    scheduler: Spinlock<maitake::scheduler::Scheduler>,
    pub timer: maitake::time::Timer,
}

impl TaskletScheduler {
    pub fn new() -> TaskletScheduler {
        TaskletScheduler {
            scheduler: Spinlock::new(maitake::scheduler::Scheduler::new()),
            // TODO: probs need to be able to supply a tick granularity?
            timer: maitake::time::Timer::new(Duration::from_millis(20)),
        }
    }

    pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
    where
        F: Future + Send + 'static,
        F::Output: Send + 'static,
    {
        let scheduler = self.scheduler.lock();
        scheduler.spawn(future)
    }

    pub fn tick(&self) {
        self.scheduler.lock().tick();
    }

    pub fn advance_timer(&self, ticks: u64) {
        self.timer.advance_ticks(1);
    }
}