Skip to content

Commit 9887c12

Browse files
committed
Keep task in map instead of repeatedly removing it
Also: Use entry API on waker_cache map.
1 parent ee0c11d commit 9887c12

File tree

1 file changed

+30
-27
lines changed

1 file changed

+30
-27
lines changed

src/task/executor.rs

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,26 @@ use core::task::{Context, Poll, Waker};
44
use crossbeam_queue::ArrayQueue;
55

66
pub struct Executor {
7+
tasks: BTreeMap<TaskId, Task>,
78
task_queue: Arc<ArrayQueue<TaskId>>,
8-
waiting_tasks: BTreeMap<TaskId, Task>,
99
waker_cache: BTreeMap<TaskId, Waker>,
1010
}
1111

1212
impl Executor {
1313
pub fn new() -> Self {
1414
Executor {
15+
tasks: BTreeMap::new(),
1516
task_queue: Arc::new(ArrayQueue::new(100)),
16-
waiting_tasks: BTreeMap::new(),
1717
waker_cache: BTreeMap::new(),
1818
}
1919
}
2020

2121
pub fn spawn(&mut self, task: Task) {
2222
let task_id = task.id;
23-
self.add_waiting(task);
24-
self.task_queue.push(task_id).expect("task_queue full");
23+
if self.tasks.insert(task.id, task).is_some() {
24+
panic!("task with same ID already in tasks");
25+
}
26+
self.task_queue.push(task_id).expect("queue full");
2527
}
2628

2729
pub fn run(&mut self) -> ! {
@@ -31,29 +33,30 @@ impl Executor {
3133
}
3234
}
3335

34-
fn add_waiting(&mut self, task: Task) {
35-
if self.waiting_tasks.insert(task.id, task).is_some() {
36-
panic!("task with same ID already in waiting_tasks");
37-
}
38-
}
39-
4036
fn run_ready_tasks(&mut self) {
41-
while let Ok(task_id) = self.task_queue.pop() {
42-
let mut task = match self.waiting_tasks.remove(&task_id) {
37+
// destructure `self` to avoid borrow checker errors
38+
let Self {
39+
tasks,
40+
task_queue,
41+
waker_cache,
42+
} = self;
43+
44+
while let Ok(task_id) = task_queue.pop() {
45+
let task = match tasks.get_mut(&task_id) {
4346
Some(task) => task,
44-
None => continue,
47+
None => continue, // task no longer exists
4548
};
46-
if !self.waker_cache.contains_key(&task_id) {
47-
self.waker_cache.insert(task_id, self.create_waker(task_id));
48-
}
49-
let waker = self.waker_cache.get(&task_id).expect("should exist");
49+
let waker = waker_cache
50+
.entry(task_id)
51+
.or_insert_with(|| TaskWaker::new(task_id, task_queue.clone()));
5052
let mut context = Context::from_waker(waker);
5153
match task.poll(&mut context) {
5254
Poll::Ready(()) => {
53-
// task done -> remove cached waker
54-
self.waker_cache.remove(&task_id);
55+
// task done -> remove it and its cached waker
56+
tasks.remove(&task_id);
57+
waker_cache.remove(&task_id);
5558
}
56-
Poll::Pending => self.add_waiting(task),
59+
Poll::Pending => {}
5760
}
5861
}
5962
}
@@ -68,13 +71,6 @@ impl Executor {
6871
interrupts::enable();
6972
}
7073
}
71-
72-
fn create_waker(&self, task_id: TaskId) -> Waker {
73-
Waker::from(Arc::new(TaskWaker {
74-
task_id,
75-
task_queue: self.task_queue.clone(),
76-
}))
77-
}
7874
}
7975

8076
struct TaskWaker {
@@ -83,6 +79,13 @@ struct TaskWaker {
8379
}
8480

8581
impl TaskWaker {
82+
fn new(task_id: TaskId, task_queue: Arc<ArrayQueue<TaskId>>) -> Waker {
83+
Waker::from(Arc::new(TaskWaker {
84+
task_id,
85+
task_queue,
86+
}))
87+
}
88+
8689
fn wake_task(&self) {
8790
self.task_queue.push(self.task_id).expect("task_queue full");
8891
}

0 commit comments

Comments
 (0)