Simplify executor by removing separate Spawner type

This commit is contained in:
Philipp Oppermann
2020-03-08 13:07:43 +01:00
parent a5ff4261a0
commit 378159ce76
2 changed files with 20 additions and 31 deletions

View File

@@ -56,20 +56,19 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
use blog_os::task::executor::Executor; use blog_os::task::executor::Executor;
let mut executor = Executor::new(); let mut executor = Executor::new();
let spawner = executor.create_spawner(); executor.spawn(bar());
spawner.spawn(bar());
spawner.spawn(async { executor.spawn(async {
#[cfg(test)] #[cfg(test)]
test_main(); test_main();
}); });
spawner.spawn(async { executor.spawn(async {
println!("It did not crash!"); println!("It did not crash!");
}); });
spawner.spawn(blog_os::driver::timer::print_ticks()); executor.spawn(blog_os::driver::timer::print_ticks());
spawner.spawn(blog_os::driver::keyboard::print_keypresses()); executor.spawn(blog_os::driver::keyboard::print_keypresses());
executor.run(); executor.run();
} }

View File

@@ -1,5 +1,10 @@
use crate::{interrupts, println}; use crate::{interrupts, println};
use alloc::{boxed::Box, collections::BTreeMap, sync::Arc, task::Wake}; use alloc::{
boxed::Box,
collections::{BTreeMap, VecDeque},
sync::Arc,
task::Wake,
};
use core::{ use core::{
future::Future, future::Future,
pin::Pin, pin::Pin,
@@ -8,29 +13,25 @@ use core::{
use crossbeam_queue::SegQueue; use crossbeam_queue::SegQueue;
pub type Task = Pin<Box<dyn Future<Output = ()>>>; pub type Task = Pin<Box<dyn Future<Output = ()>>>;
type TaskQueue = SegQueue<Task>;
type TaskId = usize; type TaskId = usize;
type WakeQueue = SegQueue<TaskId>;
pub struct Executor { pub struct Executor {
task_queue: Arc<TaskQueue>, task_queue: VecDeque<Task>,
wake_queue: Arc<WakeQueue>, wake_queue: Arc<SegQueue<TaskId>>,
pending_tasks: BTreeMap<TaskId, Task>, pending_tasks: BTreeMap<TaskId, Task>,
} }
impl Executor { impl Executor {
pub fn new() -> Self { pub fn new() -> Self {
Executor { Executor {
task_queue: Arc::new(TaskQueue::new()), task_queue: VecDeque::new(),
wake_queue: Arc::new(WakeQueue::new()), wake_queue: Arc::new(SegQueue::new()),
pending_tasks: BTreeMap::new(), pending_tasks: BTreeMap::new(),
} }
} }
pub fn create_spawner(&self) -> Spawner { pub fn spawn(&mut self, task: impl Future<Output = ()> + 'static) {
Spawner { self.task_queue.push_back(Box::pin(task))
task_queue: self.task_queue.clone(),
}
} }
pub fn run(&mut self) -> ! { pub fn run(&mut self) -> ! {
@@ -44,13 +45,13 @@ impl Executor {
// wakeup waiting tasks // wakeup waiting tasks
while let Ok(task_id) = self.wake_queue.pop() { while let Ok(task_id) = self.wake_queue.pop() {
if let Some(task) = self.pending_tasks.remove(&task_id) { if let Some(task) = self.pending_tasks.remove(&task_id) {
self.task_queue.push(task); self.task_queue.push_back(task);
} else { } else {
println!("WARNING: woken task not found in pending_tasks"); println!("WARNING: woken task not found in pending_tasks");
} }
} }
// run ready tasks // run ready tasks
while let Ok(mut task) = self.task_queue.pop() { while let Some(mut task) = self.task_queue.pop_front() {
let waker = self.create_waker(&task).into(); let waker = self.create_waker(&task).into();
let mut context = Context::from_waker(&waker); let mut context = Context::from_waker(&waker);
match task.as_mut().poll(&mut context) { match task.as_mut().poll(&mut context) {
@@ -89,19 +90,8 @@ impl Executor {
} }
} }
#[derive(Debug, Clone)]
pub struct Spawner {
task_queue: Arc<TaskQueue>,
}
impl Spawner {
pub fn spawn(&self, task: impl Future<Output = ()> + 'static) {
self.task_queue.push(Box::pin(task))
}
}
pub struct Waker { pub struct Waker {
wake_queue: Arc<WakeQueue>, wake_queue: Arc<SegQueue<TaskId>>,
task_id: TaskId, task_id: TaskId,
} }