@@ -43,6 +43,8 @@ const DEFAULT_WAIT_THREAD_COUNT_MAX: usize = 5;
43
43
44
44
type MessageSender = Sender < ( MessageHeader , Vec < u8 > ) > ;
45
45
type MessageReceiver = Receiver < ( MessageHeader , Vec < u8 > ) > ;
46
+ type WorkloadSender = crossbeam:: channel:: Sender < ( MessageHeader , Vec < u8 > ) > ;
47
+ type WorkloadReceiver = crossbeam:: channel:: Receiver < ( MessageHeader , Vec < u8 > ) > ;
46
48
47
49
/// A ttrpc Server (sync).
48
50
pub struct Server {
@@ -78,12 +80,13 @@ impl Connection {
78
80
79
81
struct ThreadS < ' a > {
80
82
connection : & ' a Arc < PipeConnection > ,
81
- fdlock : & ' a Arc < Mutex < ( ) > > ,
83
+ workload_rx : & ' a WorkloadReceiver ,
82
84
wtc : & ' a Arc < AtomicUsize > ,
83
85
quit : & ' a Arc < AtomicBool > ,
84
86
methods : & ' a Arc < HashMap < String , Box < dyn MethodHandler + Send + Sync > > > ,
85
87
res_tx : & ' a MessageSender ,
86
88
control_tx : & ' a SyncSender < ( ) > ,
89
+ cancel_rx : & ' a crossbeam:: channel:: Receiver < ( ) > ,
87
90
default : usize ,
88
91
min : usize ,
89
92
max : usize ,
@@ -92,12 +95,13 @@ struct ThreadS<'a> {
92
95
#[ allow( clippy:: too_many_arguments) ]
93
96
fn start_method_handler_thread (
94
97
connection : Arc < PipeConnection > ,
95
- fdlock : Arc < Mutex < ( ) > > ,
98
+ workload_rx : WorkloadReceiver ,
96
99
wtc : Arc < AtomicUsize > ,
97
100
quit : Arc < AtomicBool > ,
98
101
methods : Arc < HashMap < String , Box < dyn MethodHandler + Send + Sync > > > ,
99
102
res_tx : MessageSender ,
100
103
control_tx : SyncSender < ( ) > ,
104
+ cancel_rx : crossbeam:: channel:: Receiver < ( ) > ,
101
105
min : usize ,
102
106
max : usize ,
103
107
) {
@@ -109,18 +113,7 @@ fn start_method_handler_thread(
109
113
break ;
110
114
}
111
115
112
- let result;
113
- {
114
- let _guard = fdlock. lock ( ) . unwrap ( ) ;
115
- if quit. load ( Ordering :: SeqCst ) {
116
- // notify the connection dealing main thread to stop.
117
- control_tx
118
- . send ( ( ) )
119
- . unwrap_or_else ( |err| trace ! ( "Failed to send {:?}" , err) ) ;
120
- break ;
121
- }
122
- result = read_message ( & connection) ;
123
- }
116
+ let result = workload_rx. recv ( ) ;
124
117
125
118
if quit. load ( Ordering :: SeqCst ) {
126
119
// notify the connection dealing main thread to stop.
@@ -146,22 +139,18 @@ fn start_method_handler_thread(
146
139
buf = y;
147
140
}
148
141
Err ( x) => match x {
149
- Error :: Socket ( y ) => {
150
- trace ! ( "Socket error {}" , y ) ;
142
+ crossbeam :: channel :: RecvError => {
143
+ trace ! ( "workload_rx recv error" ) ;
151
144
quit. store ( true , Ordering :: SeqCst ) ;
152
- // the client connection would be closed and
145
+ // the workload tx would be dropped and
153
146
// the connection dealing main thread would
154
147
// have exited.
155
148
control_tx
156
149
. send ( ( ) )
157
150
. unwrap_or_else ( |err| trace ! ( "Failed to send {:?}" , err) ) ;
158
- trace ! ( "Socket error send control_tx" ) ;
151
+ trace ! ( "workload_rx recv error, send control_tx" ) ;
159
152
break ;
160
153
}
161
- _ => {
162
- trace ! ( "Others error {:?}" , x) ;
163
- continue ;
164
- }
165
154
} ,
166
155
}
167
156
@@ -211,6 +200,7 @@ fn start_method_handler_thread(
211
200
} ;
212
201
let ctx = TtrpcContext {
213
202
fd : connection. id ( ) ,
203
+ cancel_rx : cancel_rx. clone ( ) ,
214
204
mh,
215
205
res_tx : res_tx. clone ( ) ,
216
206
metadata : context:: from_pb ( & req. metadata ) ,
@@ -238,12 +228,13 @@ fn start_method_handler_threads(num: usize, ts: &ThreadS) {
238
228
}
239
229
start_method_handler_thread (
240
230
ts. connection . clone ( ) ,
241
- ts. fdlock . clone ( ) ,
231
+ ts. workload_rx . clone ( ) ,
242
232
ts. wtc . clone ( ) ,
243
233
ts. quit . clone ( ) ,
244
234
ts. methods . clone ( ) ,
245
235
ts. res_tx . clone ( ) ,
246
236
ts. control_tx . clone ( ) ,
237
+ ts. cancel_rx . clone ( ) ,
247
238
ts. min ,
248
239
ts. max ,
249
240
) ;
@@ -421,16 +412,68 @@ impl Server {
421
412
trace ! ( "response thread quit" ) ;
422
413
} ) ;
423
414
424
- let pipe = pipe_connection_child. clone ( ) ;
425
415
let ( control_tx, control_rx) : ( SyncSender < ( ) > , Receiver < ( ) > ) =
426
416
sync_channel ( 0 ) ;
417
+
418
+ // start read message thread
419
+ let quit_reader = child_quit. clone ( ) ;
420
+ let pipe_reader = pipe_connection_child. clone ( ) ;
421
+ let ( workload_tx, workload_rx) : ( WorkloadSender , WorkloadReceiver ) =
422
+ crossbeam:: channel:: unbounded ( ) ;
423
+ let ( cancel_tx, cancel_rx) = crossbeam:: channel:: unbounded :: < ( ) > ( ) ;
424
+ let control_tx_reader = control_tx. clone ( ) ;
425
+ let reader = thread:: spawn ( move || {
426
+ while !quit_reader. load ( Ordering :: SeqCst ) {
427
+ let msg = read_message ( & pipe_reader) ;
428
+ match msg {
429
+ Ok ( ( x, y) ) => {
430
+ let res = workload_tx. send ( ( x, y) ) ;
431
+ match res {
432
+ Ok ( _) => { }
433
+ Err ( crossbeam:: channel:: SendError ( e) ) => {
434
+ error ! ( "Send workload error {:?}" , e) ;
435
+ quit_reader. store ( true , Ordering :: SeqCst ) ;
436
+ control_tx_reader. send ( ( ) ) . unwrap_or_else (
437
+ |err| trace ! ( "Failed to send {:?}" , err) ,
438
+ ) ;
439
+ break ;
440
+ }
441
+ }
442
+ }
443
+ Err ( x) => match x {
444
+ Error :: Socket ( y) => {
445
+ trace ! ( "Socket error {}" , y) ;
446
+ drop ( cancel_tx) ;
447
+ quit_reader. store ( true , Ordering :: SeqCst ) ;
448
+ // the client connection would be closed and
449
+ // the connection dealing main thread would
450
+ // have exited.
451
+ control_tx_reader. send ( ( ) ) . unwrap_or_else ( |err| {
452
+ trace ! ( "Failed to send {:?}" , err)
453
+ } ) ;
454
+ trace ! ( "Socket error send control_tx" ) ;
455
+ break ;
456
+ }
457
+ _ => {
458
+ trace ! ( "Other error {:?}" , x) ;
459
+ continue ;
460
+ }
461
+ } ,
462
+ }
463
+ }
464
+
465
+ trace ! ( "read message thread quit" ) ;
466
+ } ) ;
467
+
468
+ let pipe = pipe_connection_child. clone ( ) ;
427
469
let ts = ThreadS {
428
470
connection : & pipe,
429
- fdlock : & Arc :: new ( Mutex :: new ( ( ) ) ) ,
471
+ workload_rx : & workload_rx ,
430
472
wtc : & Arc :: new ( AtomicUsize :: new ( 0 ) ) ,
431
473
methods : & methods,
432
474
res_tx : & res_tx,
433
475
control_tx : & control_tx,
476
+ cancel_rx : & cancel_rx,
434
477
quit : & child_quit,
435
478
default,
436
479
min,
@@ -449,7 +492,9 @@ impl Server {
449
492
drop ( control_rx) ;
450
493
// drop the res_tx, thus the res_rx would get terminated notification.
451
494
drop ( res_tx) ;
495
+ drop ( workload_rx) ;
452
496
handler. join ( ) . unwrap_or ( ( ) ) ;
497
+ reader. join ( ) . unwrap_or ( ( ) ) ;
453
498
// client_handler should not close fd before exit
454
499
// , which prevent fd reuse issue.
455
500
reaper_tx_child. send ( pipe. id ( ) ) . unwrap ( ) ;
0 commit comments