@@ -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.
112136 pub 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