@@ -4,24 +4,26 @@ use core::task::{Context, Poll, Waker};
4
4
use crossbeam_queue:: ArrayQueue ;
5
5
6
6
pub struct Executor {
7
+ tasks : BTreeMap < TaskId , Task > ,
7
8
task_queue : Arc < ArrayQueue < TaskId > > ,
8
- waiting_tasks : BTreeMap < TaskId , Task > ,
9
9
waker_cache : BTreeMap < TaskId , Waker > ,
10
10
}
11
11
12
12
impl Executor {
13
13
pub fn new ( ) -> Self {
14
14
Executor {
15
+ tasks : BTreeMap :: new ( ) ,
15
16
task_queue : Arc :: new ( ArrayQueue :: new ( 100 ) ) ,
16
- waiting_tasks : BTreeMap :: new ( ) ,
17
17
waker_cache : BTreeMap :: new ( ) ,
18
18
}
19
19
}
20
20
21
21
pub fn spawn ( & mut self , task : Task ) {
22
22
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" ) ;
25
27
}
26
28
27
29
pub fn run ( & mut self ) -> ! {
@@ -31,29 +33,30 @@ impl Executor {
31
33
}
32
34
}
33
35
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
-
40
36
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) {
43
46
Some ( task) => task,
44
- None => continue ,
47
+ None => continue , // task no longer exists
45
48
} ;
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 ( ) ) ) ;
50
52
let mut context = Context :: from_waker ( waker) ;
51
53
match task. poll ( & mut context) {
52
54
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) ;
55
58
}
56
- Poll :: Pending => self . add_waiting ( task ) ,
59
+ Poll :: Pending => { }
57
60
}
58
61
}
59
62
}
@@ -68,13 +71,6 @@ impl Executor {
68
71
interrupts:: enable ( ) ;
69
72
}
70
73
}
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
- }
78
74
}
79
75
80
76
struct TaskWaker {
@@ -83,6 +79,13 @@ struct TaskWaker {
83
79
}
84
80
85
81
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
+
86
89
fn wake_task ( & self ) {
87
90
self . task_queue . push ( self . task_id ) . expect ( "task_queue full" ) ;
88
91
}
0 commit comments