@@ -2,7 +2,7 @@ use crate::enter;
22use  futures_core:: future:: Future ; 
33use  futures_core:: stream:: Stream ; 
44use  futures_core:: task:: { Context ,  Poll } ; 
5- use  futures_task:: { waker_ref,  ArcWake } ; 
5+ use  futures_task:: { waker_ref,  ArcWake ,   BoundLocalSpawn } ; 
66use  futures_task:: { FutureObj ,  LocalFutureObj ,  LocalSpawn ,  Spawn ,  SpawnError } ; 
77use  futures_util:: pin_mut; 
88use  futures_util:: stream:: FuturesUnordered ; 
@@ -17,6 +17,36 @@ use std::sync::{
1717use  std:: thread:: { self ,  Thread } ; 
1818use  std:: vec:: Vec ; 
1919
20+ /// A single-threaded task pool with bound lifetime for polling futures to 
21+ /// completion. 
22+ /// 
23+ /// This executor allows you to multiplex any number of tasks onto a single 
24+ /// thread. It's appropriate to poll strictly I/O-bound futures that do very 
25+ /// little work in between I/O actions. The lifetime of the executor is bound by 
26+ /// a generic parameter. Futures associated with the executor need only outlive 
27+ /// this lifetime. That uncompleted futures are dropped when the lifetime of the 
28+ /// executor expires. 
29+ /// 
30+ /// To get a handle to the pool that implements [`Spawn`](futures_task::Spawn), 
31+ /// use the [`spawner()`](BoundLocalPool::spawner) method. Because the executor 
32+ /// is single-threaded, it supports a special form of task spawning for 
33+ /// non-`Send` futures, via 
34+ /// [`spawn_local_obj`](futures_task::LocalSpawn::spawn_local_obj). 
35+ /// Additionally, tasks with a limited lifetime can be spawned via 
36+ /// [`spawn_bound_local_obj`](futures_task::BoundLocalSpawn::spawn_bound_local_obj). 
37+ #[ derive( Debug ) ]  
38+ pub  struct  BoundLocalPool < ' a >  { 
39+     pool :  FuturesUnordered < LocalFutureObj < ' a ,  ( ) > > , 
40+     incoming :  Rc < Incoming < ' a > > , 
41+ } 
42+ 
43+ /// A handle to a [`BoundLocalPool`] that implements 
44+ /// [`BoundLocalSpawn`](futures_task::BoundLocalSpawn). 
45+ #[ derive( Clone ,  Debug ) ]  
46+ pub  struct  BoundLocalSpawner < ' a >  { 
47+     incoming :  Weak < Incoming < ' a > > , 
48+ } 
49+ 
2050/// A single-threaded task pool for polling futures to completion. 
2151/// 
2252/// This executor allows you to multiplex any number of tasks onto a single 
@@ -28,19 +58,13 @@ use std::vec::Vec;
2858/// [`spawner()`](LocalPool::spawner) method. Because the executor is 
2959/// single-threaded, it supports a special form of task spawning for non-`Send` 
3060/// futures, via [`spawn_local_obj`](futures_task::LocalSpawn::spawn_local_obj). 
31- #[ derive( Debug ) ]  
32- pub  struct  LocalPool  { 
33-     pool :  FuturesUnordered < LocalFutureObj < ' static ,  ( ) > > , 
34-     incoming :  Rc < Incoming > , 
35- } 
61+ pub  type  LocalPool  = BoundLocalPool < ' static > ; 
3662
37- /// A handle to a [`LocalPool`] that implements [`Spawn`](futures_task::Spawn). 
38- #[ derive( Clone ,  Debug ) ]  
39- pub  struct  LocalSpawner  { 
40-     incoming :  Weak < Incoming > , 
41- } 
63+ /// A handle to a [`LocalPool`] that implements [`Spawn`](futures_task::Spawn) 
64+ /// and [`LocalSpawn`](futures_task::LocalSpawn). 
65+ pub  type  LocalSpawner  = BoundLocalSpawner < ' static > ; 
4266
43- type  Incoming  = RefCell < Vec < LocalFutureObj < ' static ,  ( ) > > > ; 
67+ type  Incoming < ' a >  = RefCell < Vec < LocalFutureObj < ' a ,  ( ) > > > ; 
4468
4569pub ( crate )  struct  ThreadNotify  { 
4670    /// The (single) executor thread. 
@@ -107,15 +131,15 @@ fn woken() -> bool {
107131    CURRENT_THREAD_NOTIFY . with ( |thread_notify| thread_notify. unparked . load ( Ordering :: Acquire ) ) 
108132} 
109133
110- impl   LocalPool  { 
134+ impl < ' a >   BoundLocalPool < ' a >  { 
111135    /// Create a new, empty pool of tasks. 
112136pub  fn  new ( )  -> Self  { 
113137        Self  {  pool :  FuturesUnordered :: new ( ) ,  incoming :  Default :: default ( )  } 
114138    } 
115139
116140    /// Get a clonable handle to the pool as a [`Spawn`]. 
117- pub  fn  spawner ( & self )  -> LocalSpawner  { 
118-         LocalSpawner  {  incoming :  Rc :: downgrade ( & self . incoming )  } 
141+ pub  fn  spawner ( & self )  -> BoundLocalSpawner < ' a >  { 
142+         BoundLocalSpawner  {  incoming :  Rc :: downgrade ( & self . incoming )  } 
119143    } 
120144
121145    /// Run all tasks in the pool to completion. 
@@ -362,7 +386,7 @@ impl<S: Stream + Unpin> Iterator for BlockingStream<S> {
362386    } 
363387} 
364388
365- impl  Spawn  for  LocalSpawner  { 
389+ impl  Spawn  for  BoundLocalSpawner < ' _ >  { 
366390    fn  spawn_obj ( & self ,  future :  FutureObj < ' static ,  ( ) > )  -> Result < ( ) ,  SpawnError >  { 
367391        if  let  Some ( incoming)  = self . incoming . upgrade ( )  { 
368392            incoming. borrow_mut ( ) . push ( future. into ( ) ) ; 
@@ -381,7 +405,7 @@ impl Spawn for LocalSpawner {
381405    } 
382406} 
383407
384- impl  LocalSpawn  for  LocalSpawner  { 
408+ impl  LocalSpawn  for  BoundLocalSpawner < ' _ >  { 
385409    fn  spawn_local_obj ( & self ,  future :  LocalFutureObj < ' static ,  ( ) > )  -> Result < ( ) ,  SpawnError >  { 
386410        if  let  Some ( incoming)  = self . incoming . upgrade ( )  { 
387411            incoming. borrow_mut ( ) . push ( future) ; 
@@ -399,3 +423,14 @@ impl LocalSpawn for LocalSpawner {
399423        } 
400424    } 
401425} 
426+ 
427+ impl < ' a >  BoundLocalSpawn < ' a >  for  BoundLocalSpawner < ' a >  { 
428+     fn  spawn_bound_local_obj ( & self ,  future :  LocalFutureObj < ' a ,  ( ) > )  -> Result < ( ) ,  SpawnError >  { 
429+         if  let  Some ( incoming)  = self . incoming . upgrade ( )  { 
430+             incoming. borrow_mut ( ) . push ( future) ; 
431+             Ok ( ( ) ) 
432+         }  else  { 
433+             Err ( SpawnError :: shutdown ( ) ) 
434+         } 
435+     } 
436+ } 
0 commit comments