@@ -2,7 +2,7 @@ use crate::enter;
2
2
use futures_core:: future:: Future ;
3
3
use futures_core:: stream:: Stream ;
4
4
use futures_core:: task:: { Context , Poll } ;
5
- use futures_task:: { waker_ref, ArcWake } ;
5
+ use futures_task:: { waker_ref, ArcWake , BoundLocalSpawn } ;
6
6
use futures_task:: { FutureObj , LocalFutureObj , LocalSpawn , Spawn , SpawnError } ;
7
7
use futures_util:: pin_mut;
8
8
use futures_util:: stream:: FuturesUnordered ;
@@ -17,6 +17,36 @@ use std::sync::{
17
17
use std:: thread:: { self , Thread } ;
18
18
use std:: vec:: Vec ;
19
19
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
+
20
50
/// A single-threaded task pool for polling futures to completion.
21
51
///
22
52
/// This executor allows you to multiplex any number of tasks onto a single
@@ -28,19 +58,13 @@ use std::vec::Vec;
28
58
/// [`spawner()`](LocalPool::spawner) method. Because the executor is
29
59
/// single-threaded, it supports a special form of task spawning for non-`Send`
30
60
/// 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 > ;
36
62
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 > ;
42
66
43
- type Incoming = RefCell < Vec < LocalFutureObj < ' static , ( ) > > > ;
67
+ type Incoming < ' a > = RefCell < Vec < LocalFutureObj < ' a , ( ) > > > ;
44
68
45
69
pub ( crate ) struct ThreadNotify {
46
70
/// The (single) executor thread.
@@ -107,15 +131,15 @@ fn woken() -> bool {
107
131
CURRENT_THREAD_NOTIFY . with ( |thread_notify| thread_notify. unparked . load ( Ordering :: Acquire ) )
108
132
}
109
133
110
- impl LocalPool {
134
+ impl < ' a > BoundLocalPool < ' a > {
111
135
/// Create a new, empty pool of tasks.
112
136
pub fn new ( ) -> Self {
113
137
Self { pool : FuturesUnordered :: new ( ) , incoming : Default :: default ( ) }
114
138
}
115
139
116
140
/// 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 ) }
119
143
}
120
144
121
145
/// Run all tasks in the pool to completion.
@@ -362,7 +386,7 @@ impl<S: Stream + Unpin> Iterator for BlockingStream<S> {
362
386
}
363
387
}
364
388
365
- impl Spawn for LocalSpawner {
389
+ impl Spawn for BoundLocalSpawner < ' _ > {
366
390
fn spawn_obj ( & self , future : FutureObj < ' static , ( ) > ) -> Result < ( ) , SpawnError > {
367
391
if let Some ( incoming) = self . incoming . upgrade ( ) {
368
392
incoming. borrow_mut ( ) . push ( future. into ( ) ) ;
@@ -381,7 +405,7 @@ impl Spawn for LocalSpawner {
381
405
}
382
406
}
383
407
384
- impl LocalSpawn for LocalSpawner {
408
+ impl LocalSpawn for BoundLocalSpawner < ' _ > {
385
409
fn spawn_local_obj ( & self , future : LocalFutureObj < ' static , ( ) > ) -> Result < ( ) , SpawnError > {
386
410
if let Some ( incoming) = self . incoming . upgrade ( ) {
387
411
incoming. borrow_mut ( ) . push ( future) ;
@@ -399,3 +423,14 @@ impl LocalSpawn for LocalSpawner {
399
423
}
400
424
}
401
425
}
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