@@ -4,24 +4,26 @@ use core::task::{Context, Poll, Waker};
44use crossbeam_queue:: ArrayQueue ;
55
66pub 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
1212impl 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
8076struct TaskWaker {
@@ -83,6 +79,13 @@ struct TaskWaker {
8379}
8480
8581impl 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