22
33use  super :: * ; 
44
5+ use  std:: marker:: PhantomData ; 
6+ 
57// FIXME(eddyb) generate the definition of `HandleStore` in `server.rs`. 
68use  super :: client:: HandleStore ; 
79
@@ -143,6 +145,41 @@ pub trait ExecutionStrategy {
143145    )  -> Buffer ; 
144146} 
145147
148+ pub  struct  MaybeCrossThread < P >  { 
149+     cross_thread :  bool , 
150+     marker :  PhantomData < P > , 
151+ } 
152+ 
153+ impl < P >  MaybeCrossThread < P >  { 
154+     pub  const  fn  new ( cross_thread :  bool )  -> Self  { 
155+         MaybeCrossThread  {  cross_thread,  marker :  PhantomData  } 
156+     } 
157+ } 
158+ 
159+ impl < P >  ExecutionStrategy  for  MaybeCrossThread < P > 
160+ where 
161+     P :  MessagePipe < Buffer >  + Send  + ' static , 
162+ { 
163+     fn  run_bridge_and_client ( 
164+         & self , 
165+         dispatcher :  & mut  impl  DispatcherTrait , 
166+         input :  Buffer , 
167+         run_client :  extern  "C"  fn ( BridgeConfig < ' _ > )  -> Buffer , 
168+         force_show_panics :  bool , 
169+     )  -> Buffer  { 
170+         if  self . cross_thread  { 
171+             <CrossThread < P > >:: new ( ) . run_bridge_and_client ( 
172+                 dispatcher, 
173+                 input, 
174+                 run_client, 
175+                 force_show_panics, 
176+             ) 
177+         }  else  { 
178+             SameThread . run_bridge_and_client ( dispatcher,  input,  run_client,  force_show_panics) 
179+         } 
180+     } 
181+ } 
182+ 
146183pub  struct  SameThread ; 
147184
148185impl  ExecutionStrategy  for  SameThread  { 
@@ -164,28 +201,31 @@ impl ExecutionStrategy for SameThread {
164201    } 
165202} 
166203
167- // NOTE(eddyb) Two implementations are provided, the second one is a bit 
168- // faster but neither is anywhere near as fast as same-thread execution. 
204+ pub  struct  CrossThread < P > ( PhantomData < P > ) ; 
169205
170- pub  struct  CrossThread1 ; 
206+ impl < P >  CrossThread < P >  { 
207+     pub  const  fn  new ( )  -> Self  { 
208+         CrossThread ( PhantomData ) 
209+     } 
210+ } 
171211
172- impl  ExecutionStrategy  for  CrossThread1  { 
212+ impl < P >  ExecutionStrategy  for  CrossThread < P > 
213+ where 
214+     P :  MessagePipe < Buffer >  + Send  + ' static , 
215+ { 
173216    fn  run_bridge_and_client ( 
174217        & self , 
175218        dispatcher :  & mut  impl  DispatcherTrait , 
176219        input :  Buffer , 
177220        run_client :  extern  "C"  fn ( BridgeConfig < ' _ > )  -> Buffer , 
178221        force_show_panics :  bool , 
179222    )  -> Buffer  { 
180-         use  std:: sync:: mpsc:: channel; 
181- 
182-         let  ( req_tx,  req_rx)  = channel ( ) ; 
183-         let  ( res_tx,  res_rx)  = channel ( ) ; 
223+         let  ( mut  server,  mut  client)  = P :: new ( ) ; 
184224
185225        let  join_handle = thread:: spawn ( move  || { 
186-             let  mut  dispatch = |buf|  { 
187-                 req_tx . send ( buf ) . unwrap ( ) ; 
188-                 res_rx . recv ( ) . unwrap ( ) 
226+             let  mut  dispatch = |b :   Buffer | ->  Buffer  { 
227+                 client . send ( b ) ; 
228+                 client . recv ( ) . expect ( "server died while client waiting for reply" ) 
189229            } ; 
190230
191231            run_client ( BridgeConfig  { 
@@ -196,75 +236,27 @@ impl ExecutionStrategy for CrossThread1 {
196236            } ) 
197237        } ) ; 
198238
199-         for  b  in  req_rx  { 
200-             res_tx . send ( dispatcher. dispatch ( b) ) . unwrap ( ) ; 
239+         while   let   Some ( b )  = server . recv ( )  { 
240+             server . send ( dispatcher. dispatch ( b) ) ; 
201241        } 
202242
203243        join_handle. join ( ) . unwrap ( ) 
204244    } 
205245} 
206246
207- pub  struct  CrossThread2 ; 
247+ /// A message pipe used for communicating between server and client threads. 
248+ pub  trait  MessagePipe < T > :  Sized  { 
249+     /// Create a new pair of endpoints for the message pipe. 
250+ fn  new ( )  -> ( Self ,  Self ) ; 
208251
209- impl  ExecutionStrategy  for  CrossThread2  { 
210-     fn  run_bridge_and_client ( 
211-         & self , 
212-         dispatcher :  & mut  impl  DispatcherTrait , 
213-         input :  Buffer , 
214-         run_client :  extern  "C"  fn ( BridgeConfig < ' _ > )  -> Buffer , 
215-         force_show_panics :  bool , 
216-     )  -> Buffer  { 
217-         use  std:: sync:: { Arc ,  Mutex } ; 
218- 
219-         enum  State < T >  { 
220-             Req ( T ) , 
221-             Res ( T ) , 
222-         } 
223- 
224-         let  mut  state = Arc :: new ( Mutex :: new ( State :: Res ( Buffer :: new ( ) ) ) ) ; 
225- 
226-         let  server_thread = thread:: current ( ) ; 
227-         let  state2 = state. clone ( ) ; 
228-         let  join_handle = thread:: spawn ( move  || { 
229-             let  mut  dispatch = |b| { 
230-                 * state2. lock ( ) . unwrap ( )  = State :: Req ( b) ; 
231-                 server_thread. unpark ( ) ; 
232-                 loop  { 
233-                     thread:: park ( ) ; 
234-                     if  let  State :: Res ( b)  = & mut  * state2. lock ( ) . unwrap ( )  { 
235-                         break  b. take ( ) ; 
236-                     } 
237-                 } 
238-             } ; 
239- 
240-             let  r = run_client ( BridgeConfig  { 
241-                 input, 
242-                 dispatch :  ( & mut  dispatch) . into ( ) , 
243-                 force_show_panics, 
244-                 _marker :  marker:: PhantomData , 
245-             } ) ; 
246- 
247-             // Wake up the server so it can exit the dispatch loop. 
248-             drop ( state2) ; 
249-             server_thread. unpark ( ) ; 
250- 
251-             r
252-         } ) ; 
253- 
254-         // Check whether `state2` was dropped, to know when to stop. 
255-         while  Arc :: get_mut ( & mut  state) . is_none ( )  { 
256-             thread:: park ( ) ; 
257-             let  mut  b = match  & mut  * state. lock ( ) . unwrap ( )  { 
258-                 State :: Req ( b)  => b. take ( ) , 
259-                 _ => continue , 
260-             } ; 
261-             b = dispatcher. dispatch ( b. take ( ) ) ; 
262-             * state. lock ( ) . unwrap ( )  = State :: Res ( b) ; 
263-             join_handle. thread ( ) . unpark ( ) ; 
264-         } 
252+     /// Send a message to the other endpoint of this pipe. 
253+ fn  send ( & mut  self ,  value :  T ) ; 
265254
266-         join_handle. join ( ) . unwrap ( ) 
267-     } 
255+     /// Receive a message from the other endpoint of this pipe. 
256+ /// 
257+ /// Returns `None` if the other end of the pipe has been destroyed, and no 
258+ /// message was received. 
259+ fn  recv ( & mut  self )  -> Option < T > ; 
268260} 
269261
270262fn  run_server < 
0 commit comments