@@ -11,14 +11,14 @@ use std::{
11
11
thread:: { available_parallelism, JoinHandle } ,
12
12
} ;
13
13
14
- use compio_driver:: { AsyncifyPool , ProactorBuilder } ;
14
+ use compio_driver:: { AsyncifyPool , DispatchError , Dispatchable , ProactorBuilder } ;
15
15
use compio_runtime:: { event:: Event , JoinHandle as CompioJoinHandle , Runtime } ;
16
16
use flume:: { unbounded, SendError , Sender } ;
17
17
use futures_channel:: oneshot;
18
18
19
- type Dispatching = Box < dyn Dispatchable + Send > ;
19
+ type Spawning = Box < dyn Spawnable + Send > ;
20
20
21
- trait Dispatchable {
21
+ trait Spawnable {
22
22
fn spawn ( self : Box < Self > , handle : & Runtime ) -> CompioJoinHandle < ( ) > ;
23
23
}
24
24
@@ -28,7 +28,14 @@ struct Concrete<F, R> {
28
28
func : F ,
29
29
}
30
30
31
- impl < F , Fut , R > Dispatchable for Concrete < F , R >
31
+ impl < F , R > Concrete < F , R > {
32
+ pub fn new ( func : F ) -> ( Self , oneshot:: Receiver < R > ) {
33
+ let ( tx, rx) = oneshot:: channel ( ) ;
34
+ ( Self { callback : tx, func } , rx)
35
+ }
36
+ }
37
+
38
+ impl < F , Fut , R > Spawnable for Concrete < F , R >
32
39
where
33
40
F : FnOnce ( ) -> Fut + Send + ' static ,
34
41
Fut : Future < Output = R > ,
@@ -43,10 +50,22 @@ where
43
50
}
44
51
}
45
52
46
- #[ derive( Debug ) ]
53
+ impl < F , R > Dispatchable for Concrete < F , R >
54
+ where
55
+ F : FnOnce ( ) -> R + Send + ' static ,
56
+ R : Send + ' static ,
57
+ {
58
+ fn run ( self : Box < Self > ) {
59
+ let Concrete { callback, func } = * self ;
60
+ let res = func ( ) ;
61
+ callback. send ( res) . ok ( ) ;
62
+ }
63
+ }
64
+
47
65
/// The dispatcher. It manages the threads and dispatches the tasks.
66
+ #[ derive( Debug ) ]
48
67
pub struct Dispatcher {
49
- sender : Sender < Dispatching > ,
68
+ sender : Sender < Spawning > ,
50
69
threads : Vec < JoinHandle < ( ) > > ,
51
70
pool : AsyncifyPool ,
52
71
}
@@ -57,7 +76,7 @@ impl Dispatcher {
57
76
let mut proactor_builder = builder. proactor_builder ;
58
77
proactor_builder. force_reuse_thread_pool ( ) ;
59
78
let pool = proactor_builder. create_or_get_thread_pool ( ) ;
60
- let ( sender, receiver) = unbounded :: < Dispatching > ( ) ;
79
+ let ( sender, receiver) = unbounded :: < Spawning > ( ) ;
61
80
62
81
let threads = ( 0 ..builder. nthreads )
63
82
. map ( {
@@ -129,11 +148,8 @@ impl Dispatcher {
129
148
Fut : Future < Output = R > + ' static ,
130
149
R : Send + ' static ,
131
150
{
132
- let ( tx, rx) = oneshot:: channel ( ) ;
133
- let concrete: Concrete < Fn , R > = Concrete {
134
- callback : tx,
135
- func : f,
136
- } ;
151
+ let ( concrete, rx) = Concrete :: new ( f) ;
152
+
137
153
match self . sender . send ( Box :: new ( concrete) ) {
138
154
Ok ( _) => Ok ( rx) ,
139
155
Err ( err) => {
@@ -157,11 +173,18 @@ impl Dispatcher {
157
173
/// return an error with the original closure. The limit can be configured
158
174
/// with [`DispatcherBuilder::proactor_builder`] and
159
175
/// [`ProactorBuilder::thread_pool_limit`].
160
- pub fn dispatch_blocking < Fn > ( & self , f : Fn ) -> Result < ( ) , SendError < Fn > >
176
+ pub fn dispatch_blocking < Fn , R > ( & self , f : Fn ) -> Result < oneshot :: Receiver < R > , DispatchError < Fn > >
161
177
where
162
- Fn : FnOnce ( ) + Send + ' static ,
178
+ Fn : FnOnce ( ) -> R + Send + ' static ,
179
+ R : Send + ' static ,
163
180
{
164
- self . pool . dispatch ( f) . map_err ( |f| SendError ( f) )
181
+ let ( concrete, rx) = Concrete :: new ( f) ;
182
+
183
+ self . pool
184
+ . dispatch ( concrete)
185
+ . map_err ( |e| DispatchError ( e. 0 . func ) ) ?;
186
+
187
+ Ok ( rx)
165
188
}
166
189
167
190
/// Stop the dispatcher and wait for the threads to complete. If there is a
@@ -182,7 +205,7 @@ impl Dispatcher {
182
205
handle. notify ( ) ;
183
206
}
184
207
} ) {
185
- std:: thread:: spawn ( f) ;
208
+ std:: thread:: spawn ( f. 0 ) ;
186
209
}
187
210
event. wait ( ) . await ;
188
211
let mut guard = results. lock ( ) . unwrap ( ) ;
0 commit comments