2
2
3
3
use super :: * ;
4
4
5
+ use std:: marker:: PhantomData ;
6
+
5
7
// FIXME(eddyb) generate the definition of `HandleStore` in `server.rs`.
6
8
use super :: client:: HandleStore ;
7
9
@@ -174,6 +176,50 @@ pub trait ExecutionStrategy {
174
176
) -> Buffer < u8 > ;
175
177
}
176
178
179
+ pub struct MaybeCrossThread < P > {
180
+ cross_thread : bool ,
181
+ marker : PhantomData < P > ,
182
+ }
183
+
184
+ impl < P > MaybeCrossThread < P > {
185
+ pub const fn new ( cross_thread : bool ) -> Self {
186
+ MaybeCrossThread { cross_thread, marker : PhantomData }
187
+ }
188
+ }
189
+
190
+ impl < P > ExecutionStrategy for MaybeCrossThread < P >
191
+ where
192
+ P : MessagePipe < Buffer < u8 > > + Send + ' static ,
193
+ {
194
+ fn run_bridge_and_client < D : Copy + Send + ' static > (
195
+ & self ,
196
+ dispatcher : & mut impl DispatcherTrait ,
197
+ input : Buffer < u8 > ,
198
+ run_client : extern "C" fn ( BridgeConfig < ' _ > , D ) -> Buffer < u8 > ,
199
+ client_data : D ,
200
+ force_show_panics : bool ,
201
+ ) -> Buffer < u8 > {
202
+ if self . cross_thread {
203
+ <CrossThread < P > >:: new ( ) . run_bridge_and_client (
204
+ dispatcher,
205
+ input,
206
+ run_client,
207
+ client_data,
208
+ force_show_panics,
209
+ )
210
+ } else {
211
+ SameThread . run_bridge_and_client (
212
+ dispatcher,
213
+ input,
214
+ run_client,
215
+ client_data,
216
+ force_show_panics,
217
+ )
218
+ }
219
+ }
220
+ }
221
+
222
+ #[ derive( Default ) ]
177
223
pub struct SameThread ;
178
224
179
225
impl ExecutionStrategy for SameThread {
@@ -194,12 +240,18 @@ impl ExecutionStrategy for SameThread {
194
240
}
195
241
}
196
242
197
- // NOTE(eddyb) Two implementations are provided, the second one is a bit
198
- // faster but neither is anywhere near as fast as same-thread execution.
243
+ pub struct CrossThread < P > ( PhantomData < P > ) ;
199
244
200
- pub struct CrossThread1 ;
245
+ impl < P > CrossThread < P > {
246
+ pub const fn new ( ) -> Self {
247
+ CrossThread ( PhantomData )
248
+ }
249
+ }
201
250
202
- impl ExecutionStrategy for CrossThread1 {
251
+ impl < P > ExecutionStrategy for CrossThread < P >
252
+ where
253
+ P : MessagePipe < Buffer < u8 > > + Send + ' static ,
254
+ {
203
255
fn run_bridge_and_client < D : Copy + Send + ' static > (
204
256
& self ,
205
257
dispatcher : & mut impl DispatcherTrait ,
@@ -208,15 +260,18 @@ impl ExecutionStrategy for CrossThread1 {
208
260
client_data : D ,
209
261
force_show_panics : bool ,
210
262
) -> Buffer < u8 > {
211
- use std:: sync:: mpsc:: channel;
212
-
213
- let ( req_tx, req_rx) = channel ( ) ;
214
- let ( res_tx, res_rx) = channel ( ) ;
263
+ let ( mut server, mut client) = P :: new ( ) ;
215
264
216
265
let join_handle = thread:: spawn ( move || {
217
- let mut dispatch = |b| {
218
- req_tx. send ( b) . unwrap ( ) ;
219
- res_rx. recv ( ) . unwrap ( )
266
+ let mut dispatch = |b : Buffer < u8 > | -> Buffer < u8 > {
267
+ let method_tag = api_tags:: Method :: decode ( & mut & b[ ..] , & mut ( ) ) ;
268
+ client. send ( b) ;
269
+
270
+ if method_tag. should_wait ( ) {
271
+ client. recv ( ) . expect ( "server died while client waiting for reply" )
272
+ } else {
273
+ Buffer :: new ( )
274
+ }
220
275
} ;
221
276
222
277
run_client (
@@ -225,73 +280,55 @@ impl ExecutionStrategy for CrossThread1 {
225
280
)
226
281
} ) ;
227
282
228
- for b in req_rx {
229
- res_tx. send ( dispatcher. dispatch ( b) ) . unwrap ( ) ;
283
+ while let Some ( b) = server. recv ( ) {
284
+ let method_tag = api_tags:: Method :: decode ( & mut & b[ ..] , & mut ( ) ) ;
285
+ let b = dispatcher. dispatch ( b) ;
286
+
287
+ if method_tag. should_wait ( ) {
288
+ server. send ( b) ;
289
+ } else if let Err ( err) = <Result < ( ) , PanicMessage > >:: decode ( & mut & b[ ..] , & mut ( ) ) {
290
+ panic:: resume_unwind ( err. into ( ) ) ;
291
+ }
230
292
}
231
293
232
294
join_handle. join ( ) . unwrap ( )
233
295
}
234
296
}
235
297
236
- pub struct CrossThread2 ;
237
-
238
- impl ExecutionStrategy for CrossThread2 {
239
- fn run_bridge_and_client < D : Copy + Send + ' static > (
240
- & self ,
241
- dispatcher : & mut impl DispatcherTrait ,
242
- input : Buffer < u8 > ,
243
- run_client : extern "C" fn ( BridgeConfig < ' _ > , D ) -> Buffer < u8 > ,
244
- client_data : D ,
245
- force_show_panics : bool ,
246
- ) -> Buffer < u8 > {
247
- use std:: sync:: { Arc , Mutex } ;
248
-
249
- enum State < T > {
250
- Req ( T ) ,
251
- Res ( T ) ,
252
- }
253
-
254
- let mut state = Arc :: new ( Mutex :: new ( State :: Res ( Buffer :: new ( ) ) ) ) ;
298
+ /// A message pipe used for communicating between server and client threads.
299
+ pub trait MessagePipe < T > : Sized {
300
+ /// Create a new pair of endpoints for the message pipe.
301
+ fn new ( ) -> ( Self , Self ) ;
255
302
256
- let server_thread = thread:: current ( ) ;
257
- let state2 = state. clone ( ) ;
258
- let join_handle = thread:: spawn ( move || {
259
- let mut dispatch = |b| {
260
- * state2. lock ( ) . unwrap ( ) = State :: Req ( b) ;
261
- server_thread. unpark ( ) ;
262
- loop {
263
- thread:: park ( ) ;
264
- if let State :: Res ( b) = & mut * state2. lock ( ) . unwrap ( ) {
265
- break b. take ( ) ;
266
- }
267
- }
268
- } ;
303
+ /// Send a message to the other endpoint of this pipe.
304
+ fn send ( & mut self , value : T ) ;
269
305
270
- let r = run_client (
271
- BridgeConfig { input, dispatch : ( & mut dispatch) . into ( ) , force_show_panics } ,
272
- client_data,
273
- ) ;
306
+ /// Receive a message from the other endpoint of this pipe.
307
+ ///
308
+ /// Returns `None` if the other end of the pipe has been destroyed, and no
309
+ /// message was received.
310
+ fn recv ( & mut self ) -> Option < T > ;
311
+ }
274
312
275
- // Wake up the server so it can exit the dispatch loop.
276
- drop ( state2) ;
277
- server_thread. unpark ( ) ;
313
+ /// Implementation of `MessagePipe` using `std::sync::mpsc`
314
+ pub struct StdMessagePipe < T > {
315
+ tx : std:: sync:: mpsc:: Sender < T > ,
316
+ rx : std:: sync:: mpsc:: Receiver < T > ,
317
+ }
278
318
279
- r
280
- } ) ;
319
+ impl < T > MessagePipe < T > for StdMessagePipe < T > {
320
+ fn new ( ) -> ( Self , Self ) {
321
+ let ( tx1, rx1) = std:: sync:: mpsc:: channel ( ) ;
322
+ let ( tx2, rx2) = std:: sync:: mpsc:: channel ( ) ;
323
+ ( StdMessagePipe { tx : tx1, rx : rx2 } , StdMessagePipe { tx : tx2, rx : rx1 } )
324
+ }
281
325
282
- // Check whether `state2` was dropped, to know when to stop.
283
- while Arc :: get_mut ( & mut state) . is_none ( ) {
284
- thread:: park ( ) ;
285
- let mut b = match & mut * state. lock ( ) . unwrap ( ) {
286
- State :: Req ( b) => b. take ( ) ,
287
- _ => continue ,
288
- } ;
289
- b = dispatcher. dispatch ( b. take ( ) ) ;
290
- * state. lock ( ) . unwrap ( ) = State :: Res ( b) ;
291
- join_handle. thread ( ) . unpark ( ) ;
292
- }
326
+ fn send ( & mut self , v : T ) {
327
+ self . tx . send ( v) . unwrap ( ) ;
328
+ }
293
329
294
- join_handle. join ( ) . unwrap ( )
330
+ fn recv ( & mut self ) -> Option < T > {
331
+ self . rx . recv ( ) . ok ( )
295
332
}
296
333
}
297
334
0 commit comments