1414 * limitations under the License.
1515 */
1616
17+ use crate :: core:: future:: SizedFuture ;
1718use crate :: core:: list;
1819use crate :: core:: waker;
1920use log:: debug;
@@ -69,7 +70,7 @@ fn poll_fut(fut: &mut BoxFuture, waker: Waker) -> bool {
6970}
7071
7172struct Task {
72- fut : Option < Pin < Box < dyn Future < Output = ( ) > > > > ,
73+ fut : Option < BoxFuture > ,
7374 wakeable : bool ,
7475 low : bool ,
7576}
@@ -124,10 +125,12 @@ impl Tasks {
124125 !self . data . borrow ( ) . next . is_empty ( ) || !self . data . borrow ( ) . next_low . is_empty ( )
125126 }
126127
127- fn add < F > ( & self , fut : F ) -> Result < ( ) , ( ) >
128+ fn add < T > ( & self , get_fut : T , size : usize ) -> Result < ( ) , ( ) >
128129 where
129- F : Future < Output = ( ) > + ' static ,
130+ T : FnOnce ( ) -> BoxFuture ,
130131 {
132+ debug ! ( "spawning future with size {size}" ) ;
133+
131134 let data = & mut * self . data . borrow_mut ( ) ;
132135
133136 if data. nodes . len ( ) == data. nodes . capacity ( ) {
@@ -138,7 +141,7 @@ impl Tasks {
138141 let nkey = entry. key ( ) ;
139142
140143 let task = Task {
141- fut : Some ( Box :: pin ( fut ) ) ,
144+ fut : Some ( get_fut ( ) ) ,
142145 wakeable : false ,
143146 low : false ,
144147 } ;
@@ -340,9 +343,15 @@ impl Executor {
340343 where
341344 F : Future < Output = ( ) > + ' static ,
342345 {
343- debug ! ( "spawning future with size {}" , mem:: size_of:: <F >( ) ) ;
346+ self . tasks . add ( move || Box :: pin ( fut) , mem:: size_of :: < F > ( ) )
347+ }
348+
349+ #[ allow( clippy:: result_unit_err) ]
350+ pub fn spawn_boxed ( & self , fut : Pin < Box < dyn SizedFuture < Output = ( ) > > > ) -> Result < ( ) , ( ) > {
351+ let size = ( * fut) . size ( ) ;
352+ let fut = fut. into_future ( ) ;
344353
345- self . tasks . add ( fut)
354+ self . tasks . add ( move || fut, size )
346355 }
347356
348357 pub fn set_pre_poll < F > ( & self , pre_poll_fn : F )
@@ -473,6 +482,7 @@ impl Spawner {
473482
474483mod ffi {
475484 use super :: * ;
485+ use crate :: core:: future:: ffi:: UnitFuture ;
476486 use std:: ffi:: c_int;
477487
478488 #[ no_mangle]
@@ -514,6 +524,28 @@ mod ffi {
514524
515525 0
516526 }
527+
528+ /// Spawns `fut` on the executor in the current thread. Returns 0 on
529+ /// success or non-zero on error. An error can occur if there is no
530+ /// executor in the current thread or if the executor is at capacity.
531+ /// This function takes ownership of `fut` regardless of whether spawning
532+ /// is successful.
533+ ///
534+ /// SAFETY: `fut` must point to a valid `UnitFuture`.
535+ #[ no_mangle]
536+ pub unsafe extern "C" fn executor_current_spawn ( fut : * mut UnitFuture ) -> c_int {
537+ let Some ( executor) = Executor :: current ( ) else {
538+ return -1 ;
539+ } ;
540+
541+ let fut = Box :: from_raw ( fut) . 0 ;
542+
543+ if executor. spawn_boxed ( fut) . is_err ( ) {
544+ return -1 ;
545+ }
546+
547+ 0
548+ }
517549}
518550
519551#[ cfg( test) ]
0 commit comments