@@ -280,6 +280,20 @@ impl<C: Callback> EventLoop<C> {
280280 }
281281 }
282282
283+ /// Constructs an event loop and executes it asynchronously. `setup` is
284+ /// called just prior to executing, and `done` is called when the event
285+ /// loop exits.
286+ pub async fn task < S , D > ( registrations_max : usize , setup : S , done : D )
287+ where
288+ S : FnOnce ( & Rc < Self > ) + ' static ,
289+ D : FnOnce ( i32 ) + ' static ,
290+ {
291+ let l = Rc :: new ( Self :: new ( registrations_max) ) ;
292+ setup ( & l) ;
293+ let code = l. exec_async ( ) . await ;
294+ done ( code) ;
295+ }
296+
283297 pub fn step ( & self ) -> Option < i32 > {
284298 self . poll_and_dispatch ( Some ( Duration :: from_millis ( 0 ) ) )
285299 }
@@ -503,10 +517,10 @@ mod ffi {
503517 #[ allow( clippy:: missing_safety_doc) ]
504518 #[ no_mangle]
505519 pub unsafe extern "C" fn event_loop_step (
506- l : * mut EventLoopRaw ,
520+ l : * const EventLoopRaw ,
507521 out_code : * mut libc:: c_int ,
508522 ) -> libc:: c_int {
509- let l = l. as_mut ( ) . unwrap ( ) ;
523+ let l = l. as_ref ( ) . unwrap ( ) ;
510524
511525 match l. step ( ) {
512526 Some ( code) => {
@@ -520,31 +534,31 @@ mod ffi {
520534
521535 #[ allow( clippy:: missing_safety_doc) ]
522536 #[ no_mangle]
523- pub unsafe extern "C" fn event_loop_exec ( l : * mut EventLoopRaw ) -> libc:: c_int {
524- let l = l. as_mut ( ) . unwrap ( ) ;
537+ pub unsafe extern "C" fn event_loop_exec ( l : * const EventLoopRaw ) -> libc:: c_int {
538+ let l = l. as_ref ( ) . unwrap ( ) ;
525539
526540 l. exec ( ) as libc:: c_int
527541 }
528542
529543 #[ allow( clippy:: missing_safety_doc) ]
530544 #[ no_mangle]
531- pub unsafe extern "C" fn event_loop_exit ( l : * mut EventLoopRaw , code : libc:: c_int ) {
532- let l = l. as_mut ( ) . unwrap ( ) ;
545+ pub unsafe extern "C" fn event_loop_exit ( l : * const EventLoopRaw , code : libc:: c_int ) {
546+ let l = l. as_ref ( ) . unwrap ( ) ;
533547
534548 l. exit ( code) ;
535549 }
536550
537551 #[ allow( clippy:: missing_safety_doc) ]
538552 #[ no_mangle]
539553 pub unsafe extern "C" fn event_loop_register_fd (
540- l : * mut EventLoopRaw ,
554+ l : * const EventLoopRaw ,
541555 fd : std:: os:: raw:: c_int ,
542556 interest : u8 ,
543557 cb : unsafe extern "C" fn ( * mut libc:: c_void , u8 ) ,
544558 ctx : * mut libc:: c_void ,
545559 out_id : * mut libc:: size_t ,
546560 ) -> libc:: c_int {
547- let l = l. as_mut ( ) . unwrap ( ) ;
561+ let l = l. as_ref ( ) . unwrap ( ) ;
548562
549563 let Ok ( interest) = interest_int_to_mio ( interest) else {
550564 return -1 ;
@@ -567,13 +581,13 @@ mod ffi {
567581 #[ allow( clippy:: missing_safety_doc) ]
568582 #[ no_mangle]
569583 pub unsafe extern "C" fn event_loop_register_timer (
570- l : * mut EventLoopRaw ,
584+ l : * const EventLoopRaw ,
571585 timeout : u64 ,
572586 cb : unsafe extern "C" fn ( * mut libc:: c_void , u8 ) ,
573587 ctx : * mut libc:: c_void ,
574588 out_id : * mut libc:: size_t ,
575589 ) -> libc:: c_int {
576- let l = l. as_mut ( ) . unwrap ( ) ;
590+ let l = l. as_ref ( ) . unwrap ( ) ;
577591
578592 // SAFETY: we assume caller guarantees that the callback is safe to
579593 // call for the lifetime of the registration
@@ -592,13 +606,13 @@ mod ffi {
592606 #[ allow( clippy:: missing_safety_doc) ]
593607 #[ no_mangle]
594608 pub unsafe extern "C" fn event_loop_register_custom (
595- l : * mut EventLoopRaw ,
609+ l : * const EventLoopRaw ,
596610 cb : unsafe extern "C" fn ( * mut libc:: c_void , u8 ) ,
597611 ctx : * mut libc:: c_void ,
598612 out_id : * mut libc:: size_t ,
599613 out_set_readiness : * mut * mut event:: ffi:: SetReadiness ,
600614 ) -> libc:: c_int {
601- let l = l. as_mut ( ) . unwrap ( ) ;
615+ let l = l. as_ref ( ) . unwrap ( ) ;
602616
603617 // SAFETY: we assume caller guarantees that the callback is safe to
604618 // call for the lifetime of the registration
@@ -618,10 +632,10 @@ mod ffi {
618632 #[ allow( clippy:: missing_safety_doc) ]
619633 #[ no_mangle]
620634 pub unsafe extern "C" fn event_loop_deregister (
621- l : * mut EventLoopRaw ,
635+ l : * const EventLoopRaw ,
622636 id : libc:: size_t ,
623637 ) -> libc:: c_int {
624- let l = l. as_mut ( ) . unwrap ( ) ;
638+ let l = l. as_ref ( ) . unwrap ( ) ;
625639
626640 if l. deregister ( id) . is_err ( ) {
627641 return -1 ;
@@ -861,4 +875,86 @@ mod tests {
861875
862876 executor. run ( |timeout| reactor. poll ( timeout) ) . unwrap ( ) ;
863877 }
878+
879+ #[ test]
880+ fn task ( ) {
881+ let reactor = Reactor :: new ( 1 ) ;
882+ let executor = Executor :: new ( 1 ) ;
883+
884+ struct State {
885+ listener : Option < std:: net:: TcpListener > ,
886+ listener_reg_id : Option < usize > ,
887+ stream : Option < mio:: net:: TcpStream > ,
888+ code : Option < i32 > ,
889+ }
890+
891+ let state = Rc :: new ( RefCell :: new ( State {
892+ listener : None ,
893+ listener_reg_id : None ,
894+ stream : None ,
895+ code : None ,
896+ } ) ) ;
897+
898+ let setup_fn = {
899+ let state = Rc :: clone ( & state) ;
900+
901+ Box :: new ( move |l : & Rc < EventLoop < Box < dyn Callback > > > | {
902+ let cb = {
903+ let l = Rc :: clone ( & l) ;
904+ let state = Rc :: clone ( & state) ;
905+
906+ Box :: new ( FnCallback ( move |readiness : event:: Readiness | {
907+ assert ! ( readiness. contains_any( mio:: Interest :: READABLE ) ) ;
908+
909+ let mut state = state. borrow_mut ( ) ;
910+ let listener = state. listener . as_ref ( ) . unwrap ( ) ;
911+ let id = state. listener_reg_id . unwrap ( ) ;
912+
913+ let _stream = listener. accept ( ) . unwrap ( ) ;
914+ l. deregister ( id) . unwrap ( ) ;
915+
916+ state. listener = None ;
917+ state. listener_reg_id = None ;
918+
919+ l. exit ( 0 ) ;
920+ } ) )
921+ } ;
922+
923+ let mut state = state. borrow_mut ( ) ;
924+
925+ let listener = std:: net:: TcpListener :: bind ( "127.0.0.1:0" ) . unwrap ( ) ;
926+ listener. set_nonblocking ( true ) . unwrap ( ) ;
927+
928+ let addr = listener. local_addr ( ) . unwrap ( ) ;
929+ let fd = listener. as_raw_fd ( ) ;
930+
931+ let id = l. register_fd ( fd, mio:: Interest :: READABLE , cb) . unwrap ( ) ;
932+
933+ // non-blocking connect attempt to trigger listener
934+ let stream = mio:: net:: TcpStream :: connect ( addr) . unwrap ( ) ;
935+
936+ state. listener = Some ( listener) ;
937+ state. listener_reg_id = Some ( id) ;
938+ state. stream = Some ( stream) ;
939+ } )
940+ } ;
941+
942+ let done_fn = {
943+ let state = Rc :: clone ( & state) ;
944+
945+ Box :: new ( move |code| {
946+ state. borrow_mut ( ) . code = Some ( code) ;
947+ } )
948+ } ;
949+
950+ executor
951+ . spawn ( async {
952+ EventLoop :: < Box < dyn Callback > > :: task ( 1 , setup_fn, done_fn) . await ;
953+ } )
954+ . unwrap ( ) ;
955+
956+ executor. run ( |timeout| reactor. poll ( timeout) ) . unwrap ( ) ;
957+
958+ assert_eq ! ( state. borrow( ) . code, Some ( 0 ) ) ;
959+ }
864960}
0 commit comments