@@ -2,9 +2,13 @@ use std::error::Error as StdError;
2
2
use std:: fmt;
3
3
use std:: io;
4
4
use std:: mem;
5
+ use std:: sync:: Arc ;
5
6
//use std::net::SocketAddr;
6
7
7
8
use futures:: { Future , Poll , Async } ;
9
+ use futures:: future:: { Executor , ExecuteError } ;
10
+ use futures:: sync:: oneshot;
11
+ use futures_cpupool:: { Builder as CpuPoolBuilder } ;
8
12
use tokio_io:: { AsyncRead , AsyncWrite } ;
9
13
use tokio:: reactor:: Handle ;
10
14
use tokio:: net:: { TcpStream , TcpStreamNew } ;
@@ -43,22 +47,35 @@ where T: Service<Request=Uri, Error=io::Error> + 'static,
43
47
/// A connector for the `http` scheme.
44
48
#[ derive( Clone ) ]
45
49
pub struct HttpConnector {
46
- dns : dns :: Dns ,
50
+ executor : HttpConnectExecutor ,
47
51
enforce_http : bool ,
48
52
handle : Handle ,
49
53
}
50
54
51
55
impl HttpConnector {
52
-
53
56
/// Construct a new HttpConnector.
54
57
///
55
58
/// Takes number of DNS worker threads.
56
59
#[ inline]
57
60
pub fn new ( threads : usize , handle : & Handle ) -> HttpConnector {
61
+ let pool = CpuPoolBuilder :: new ( )
62
+ . name_prefix ( "hyper-dns" )
63
+ . pool_size ( threads)
64
+ . create ( ) ;
65
+ HttpConnector :: new_with_executor ( pool, handle)
66
+ }
67
+
68
+ /// Construct a new HttpConnector.
69
+ ///
70
+ /// Takes an executor to run blocking tasks on.
71
+ #[ inline]
72
+ pub fn new_with_executor < E : ' static > ( executor : E , handle : & Handle ) -> HttpConnector
73
+ where E : Executor < HttpConnectorBlockingTask >
74
+ {
58
75
HttpConnector {
59
- dns : dns :: Dns :: new ( threads ) ,
76
+ executor : HttpConnectExecutor ( Arc :: new ( executor ) ) ,
60
77
enforce_http : true ,
61
- handle : handle. clone ( ) ,
78
+ handle : handle. clone ( )
62
79
}
63
80
}
64
81
@@ -109,7 +126,7 @@ impl Service for HttpConnector {
109
126
} ;
110
127
111
128
HttpConnecting {
112
- state : State :: Lazy ( self . dns . clone ( ) , host. into ( ) , port) ,
129
+ state : State :: Lazy ( self . executor . clone ( ) , host. into ( ) , port) ,
113
130
handle : self . handle . clone ( ) ,
114
131
}
115
132
}
@@ -154,8 +171,8 @@ pub struct HttpConnecting {
154
171
}
155
172
156
173
enum State {
157
- Lazy ( dns :: Dns , String , u16 ) ,
158
- Resolving ( dns:: Query ) ,
174
+ Lazy ( HttpConnectExecutor , String , u16 ) ,
175
+ Resolving ( oneshot :: SpawnHandle < dns:: IpAddrs , io :: Error > ) ,
159
176
Connecting ( ConnectingTcp ) ,
160
177
Error ( Option < io:: Error > ) ,
161
178
}
@@ -168,12 +185,13 @@ impl Future for HttpConnecting {
168
185
loop {
169
186
let state;
170
187
match self . state {
171
- State :: Lazy ( ref dns , ref mut host, port) => {
188
+ State :: Lazy ( ref executor , ref mut host, port) => {
172
189
let host = mem:: replace ( host, String :: new ( ) ) ;
173
- state = State :: Resolving ( dns. resolve ( host, port) ) ;
190
+ let work = dns:: Work :: new ( host, port) ;
191
+ state = State :: Resolving ( oneshot:: spawn ( work, executor) ) ;
174
192
} ,
175
- State :: Resolving ( ref mut query ) => {
176
- match try!( query . poll ( ) ) {
193
+ State :: Resolving ( ref mut future ) => {
194
+ match try!( future . poll ( ) ) {
177
195
Async :: NotReady => return Ok ( Async :: NotReady ) ,
178
196
Async :: Ready ( addrs) => {
179
197
state = State :: Connecting ( ConnectingTcp {
@@ -231,6 +249,36 @@ impl ConnectingTcp {
231
249
}
232
250
}
233
251
252
+ /// Blocking task to be executed on a thread pool.
253
+ pub struct HttpConnectorBlockingTask {
254
+ work : oneshot:: Execute < dns:: Work >
255
+ }
256
+
257
+ impl fmt:: Debug for HttpConnectorBlockingTask {
258
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
259
+ f. pad ( "HttpConnectorBlockingTask" )
260
+ }
261
+ }
262
+
263
+ impl Future for HttpConnectorBlockingTask {
264
+ type Item = ( ) ;
265
+ type Error = ( ) ;
266
+
267
+ fn poll ( & mut self ) -> Poll < ( ) , ( ) > {
268
+ self . work . poll ( )
269
+ }
270
+ }
271
+
272
+ #[ derive( Clone ) ]
273
+ struct HttpConnectExecutor ( Arc < Executor < HttpConnectorBlockingTask > > ) ;
274
+
275
+ impl Executor < oneshot:: Execute < dns:: Work > > for HttpConnectExecutor {
276
+ fn execute ( & self , future : oneshot:: Execute < dns:: Work > ) -> Result < ( ) , ExecuteError < oneshot:: Execute < dns:: Work > > > {
277
+ self . 0 . execute ( HttpConnectorBlockingTask { work : future } )
278
+ . map_err ( |err| ExecuteError :: new ( err. kind ( ) , err. into_future ( ) . work ) )
279
+ }
280
+ }
281
+
234
282
/*
235
283
impl<S: SslClient> HttpsConnector<S> {
236
284
/// Create a new connector using the provided SSL implementation.
0 commit comments