@@ -8,6 +8,7 @@ use core::future::{poll_fn, Future};
88use core:: pin:: Pin ;
99use core:: sync:: atomic:: { AtomicBool , AtomicU64 , Ordering } ;
1010use core:: task:: { Context , Poll , Waker } ;
11+ use futures:: channel:: oneshot;
1112
1213use spin:: Mutex ;
1314use uefi:: boot:: { EventType , TimerTrigger , Tpl } ;
@@ -25,6 +26,7 @@ struct Task {
2526 future : Mutex < BoxFuture > ,
2627 micros : AtomicU64 ,
2728 last_micros : AtomicU64 ,
29+ done : AtomicBool ,
2830}
2931
3032impl Task {
@@ -38,13 +40,14 @@ impl Task {
3840 micros : AtomicU64 :: new ( 0 ) ,
3941 last_micros : AtomicU64 :: new ( 0 ) ,
4042 in_queue : AtomicBool :: new ( false ) ,
43+ done : AtomicBool :: new ( false ) ,
4144 } )
4245 }
4346}
4447
4548impl Wake for Task {
4649 fn wake ( self : Arc < Self > ) {
47- if !self . in_queue . swap ( true , Ordering :: Relaxed ) {
50+ if !self . in_queue . swap ( true , Ordering :: Relaxed ) && ! self . done . load ( Ordering :: Relaxed ) {
4851 EXECUTOR . lock ( ) . ready_tasks . push_back ( self ) ;
4952 }
5053 }
@@ -55,6 +58,14 @@ static EXECUTOR: Mutex<Executor> = Mutex::new(Executor {
5558 tasks : vec ! [ ] ,
5659} ) ;
5760
61+ pub struct JoinHandle < T > ( oneshot:: Receiver < T > ) ;
62+
63+ impl < T > JoinHandle < T > {
64+ pub async fn join ( self ) -> T {
65+ self . 0 . await . expect ( "tasks should never be cancelled" )
66+ }
67+ }
68+
5869pub struct Executor {
5970 // TODO(veluca): scheduling.
6071 ready_tasks : VecDeque < Arc < Task > > ,
@@ -145,6 +156,9 @@ impl Executor {
145156 t. last_micros
146157 . store ( t. micros . load ( Ordering :: Relaxed ) , Ordering :: Relaxed ) ;
147158 }
159+
160+ // Clear completed tasks.
161+ tasks. retain ( |t| !t. done . load ( Ordering :: Relaxed ) ) ;
148162 }
149163 last = Timer :: micros ( ) as u64 ;
150164 Self :: sleep_us ( 1_000_000 ) . await ;
@@ -165,10 +179,13 @@ impl Executor {
165179 let mut context = Context :: from_waker ( & waker) ;
166180 let mut fut = task. future . try_lock ( ) . unwrap ( ) ;
167181 let begin = Timer :: micros ( ) ;
168- let _ = fut. 0 . as_mut ( ) . poll ( & mut context) ;
182+ let done = fut. 0 . as_mut ( ) . poll ( & mut context) ;
169183 let end = Timer :: micros ( ) ;
170184 task. micros
171185 . fetch_add ( ( end - begin) as u64 , Ordering :: Relaxed ) ;
186+ if done. is_ready ( ) {
187+ task. done . swap ( true , Ordering :: Relaxed ) ;
188+ }
172189 }
173190 }
174191
@@ -211,13 +228,18 @@ impl Executor {
211228 }
212229
213230 /// Spawn a new task.
214- pub fn spawn < Fut > ( name : & ' static str , f : Fut )
231+ pub fn spawn < Fut , T : ' static > ( name : & ' static str , f : Fut ) -> JoinHandle < T >
215232 where
216- Fut : Future < Output = ( ) > + ' static ,
233+ Fut : Future < Output = T > + ' static ,
217234 {
218- let task = Task :: new ( name, f) ;
235+ let ( send, recv) = oneshot:: channel ( ) ;
236+ let task = Task :: new ( name, async move {
237+ let t = f. await ;
238+ let _ = send. send ( t) ;
239+ } ) ;
219240 let mut executor = EXECUTOR . lock ( ) ;
220241 executor. tasks . push ( task. clone ( ) ) ;
221242 executor. ready_tasks . push_back ( task) ;
243+ JoinHandle ( recv)
222244 }
223245}
0 commit comments