@@ -14,11 +14,14 @@ use std::io;
14
14
use std:: marker:: PhantomData ;
15
15
use std:: net:: SocketAddr ;
16
16
use std:: rc:: { Rc , Weak } ;
17
+ use std:: sync:: Arc ;
18
+ use std:: thread;
17
19
use std:: time:: Duration ;
18
20
19
21
use futures:: task:: { self , Task } ;
20
22
use futures:: future:: { self } ;
21
23
use futures:: { Future , Stream , Poll , Async } ;
24
+ use net2;
22
25
23
26
#[ cfg( feature = "compat" ) ]
24
27
use http;
@@ -60,7 +63,7 @@ pub struct Http<B = ::Chunk> {
60
63
keep_alive : bool ,
61
64
pipeline : bool ,
62
65
sleep_on_errors : bool ,
63
- _marker : PhantomData < B > ,
66
+ _marker : PhantomData < fn ( ) -> B > ,
64
67
}
65
68
66
69
/// An instance of a server created through `Http::bind`.
@@ -178,7 +181,7 @@ impl<B: AsRef<[u8]> + 'static> Http<B> {
178
181
{
179
182
let core = try!( Core :: new ( ) ) ;
180
183
let handle = core. handle ( ) ;
181
- let listener = try!( TcpListener :: bind ( addr, & handle) ) ;
184
+ let listener = try!( thread_listener ( addr, & handle) ) ;
182
185
183
186
Ok ( Server {
184
187
new_service : new_service,
@@ -445,6 +448,88 @@ impl<S, B> Server<S, B>
445
448
}
446
449
}
447
450
451
+
452
+ impl < S , B > Server < S , B >
453
+ where S : NewService < Request = Request , Response = Response < B > , Error = :: Error > + Send + Sync + ' static ,
454
+ B : Stream < Error =:: Error > + ' static ,
455
+ B :: Item : AsRef < [ u8 ] > ,
456
+ {
457
+ /// Run the server on multiple threads.
458
+ #[ cfg( unix) ]
459
+ pub fn run_threads ( self , threads : usize ) {
460
+ assert ! ( threads > 0 , "threads must be more than 0" ) ;
461
+
462
+ let Server {
463
+ protocol,
464
+ new_service,
465
+ reactor,
466
+ listener,
467
+ shutdown_timeout,
468
+ } = self ;
469
+
470
+ let new_service = Arc :: new ( new_service) ;
471
+ let addr = listener. local_addr ( ) . unwrap ( ) ;
472
+
473
+ let threads = ( 1 ..threads) . map ( |i| {
474
+ let protocol = protocol. clone ( ) ;
475
+ let new_service = new_service. clone ( ) ;
476
+ thread:: Builder :: new ( )
477
+ . name ( format ! ( "hyper-server-thread-{}" , i) )
478
+ . spawn ( move || {
479
+ let reactor = Core :: new ( ) . unwrap ( ) ;
480
+ let listener = thread_listener ( & addr, & reactor. handle ( ) ) . unwrap ( ) ;
481
+ let srv = Server {
482
+ protocol,
483
+ new_service,
484
+ reactor,
485
+ listener,
486
+ shutdown_timeout,
487
+ } ;
488
+ srv. run ( ) . unwrap ( ) ;
489
+ } )
490
+ . unwrap ( )
491
+ } ) . collect :: < Vec < _ > > ( ) ;
492
+
493
+ let srv = Server {
494
+ protocol,
495
+ new_service,
496
+ reactor,
497
+ listener,
498
+ shutdown_timeout,
499
+ } ;
500
+ srv. run ( ) . unwrap ( ) ;
501
+
502
+ for thread in threads {
503
+ thread. join ( ) . unwrap ( ) ;
504
+ }
505
+ }
506
+ }
507
+
508
+ fn thread_listener ( addr : & SocketAddr , handle : & Handle ) -> io:: Result < TcpListener > {
509
+ let listener = match * addr {
510
+ SocketAddr :: V4 ( _) => try!( net2:: TcpBuilder :: new_v4 ( ) ) ,
511
+ SocketAddr :: V6 ( _) => try!( net2:: TcpBuilder :: new_v6 ( ) ) ,
512
+ } ;
513
+ try!( reuse_port ( & listener) ) ;
514
+ try!( listener. reuse_address ( true ) ) ;
515
+ try!( listener. bind ( addr) ) ;
516
+ listener. listen ( 1024 ) . and_then ( |l| {
517
+ TcpListener :: from_listener ( l, addr, handle)
518
+ } )
519
+ }
520
+
521
+ #[ cfg( unix) ]
522
+ fn reuse_port ( tcp : & net2:: TcpBuilder ) -> io:: Result < ( ) > {
523
+ use net2:: unix:: * ;
524
+ try!( tcp. reuse_port ( true ) ) ;
525
+ Ok ( ( ) )
526
+ }
527
+
528
+ #[ cfg( not( unix) ) ]
529
+ fn reuse_port ( _tcp : & net2:: TcpBuilder ) -> io:: Result < ( ) > {
530
+ Ok ( ( ) )
531
+ }
532
+
448
533
impl < S : fmt:: Debug , B : Stream < Error =:: Error > > fmt:: Debug for Server < S , B >
449
534
where B :: Item : AsRef < [ u8 ] >
450
535
{
0 commit comments