1 //! Server-side traits.
5 // FIXME(eddyb) generate the definition of `HandleStore` in `server.rs`.
6 use super::client
::HandleStore
;
8 /// Declare an associated item of one of the traits below, optionally
9 /// adjusting it (i.e., adding bounds to types and default bodies to methods).
10 macro_rules
! associated_item
{
11 (type FreeFunctions
) =>
12 (type FreeFunctions
: '
static;);
14 (type TokenStream
: '
static + Clone
;);
15 (type TokenStreamBuilder
) =>
16 (type TokenStreamBuilder
: '
static;);
17 (type TokenStreamIter
) =>
18 (type TokenStreamIter
: '
static + Clone
;);
20 (type Group
: '
static + Clone
;);
22 (type Punct
: '
static + Copy
+ Eq
+ Hash
;);
24 (type Ident
: '
static + Copy
+ Eq
+ Hash
;);
26 (type Literal
: '
static + Clone
;);
28 (type SourceFile
: '
static + Clone
;);
30 (type MultiSpan
: '
static;);
32 (type Diagnostic
: '
static;);
34 (type Span
: '
static + Copy
+ Eq
+ Hash
;);
35 (fn drop(&mut self, $arg
:ident
: $arg_ty
:ty
)) =>
36 (fn drop(&mut self, $arg
: $arg_ty
) { mem::drop($arg) }
);
37 (fn clone(&mut self, $arg
:ident
: $arg_ty
:ty
) -> $ret_ty
:ty
) =>
38 (fn clone(&mut self, $arg
: $arg_ty
) -> $ret_ty { $arg.clone() }
);
39 ($
($item
:tt
)*) => ($
($item
)*;)
42 macro_rules
! declare_server_traits
{
44 $
(fn $method
:ident($
($arg
:ident
: $arg_ty
:ty
),* $
(,)?
) $
(-> $ret_ty
:ty
)?
;)*
47 $
(associated_item
!(type $name
);)*
50 $
(pub trait $name
: Types
{
51 $
(associated_item
!(fn $
method(&mut self, $
($arg
: $arg_ty
),*) $
(-> $ret_ty
)?
);)*
54 pub trait Server
: Types $
(+ $name
)* {}
55 impl<S
: Types $
(+ $name
)*> Server
for S {}
58 with_api
!(Self, self_
, declare_server_traits
);
60 pub(super) struct MarkedTypes
<S
: Types
>(S
);
62 macro_rules
! define_mark_types_impls
{
64 $
(fn $method
:ident($
($arg
:ident
: $arg_ty
:ty
),* $
(,)?
) $
(-> $ret_ty
:ty
)?
;)*
66 impl<S
: Types
> Types
for MarkedTypes
<S
> {
67 $
(type $name
= Marked
<S
::$name
, client
::$name
>;)*
70 $
(impl<S
: $name
> $name
for MarkedTypes
<S
> {
71 $
(fn $
method(&mut self, $
($arg
: $arg_ty
),*) $
(-> $ret_ty
)?
{
72 <_
>::mark($name
::$
method(&mut self.0, $
($arg
.unmark()),*))
77 with_api
!(Self, self_
, define_mark_types_impls
);
79 struct Dispatcher
<S
: Types
> {
80 handle_store
: HandleStore
<S
>,
84 macro_rules
! define_dispatcher_impl
{
86 $
(fn $method
:ident($
($arg
:ident
: $arg_ty
:ty
),* $
(,)?
) $
(-> $ret_ty
:ty
)?
;)*
88 // FIXME(eddyb) `pub` only for `ExecutionStrategy` below.
89 pub trait DispatcherTrait
{
90 // HACK(eddyb) these are here to allow `Self::$name` to work below.
92 fn dispatch(&mut self, b
: Buffer
<u8>) -> Buffer
<u8>;
95 impl<S
: Server
> DispatcherTrait
for Dispatcher
<MarkedTypes
<S
>> {
96 $
(type $name
= <MarkedTypes
<S
> as Types
>::$name
;)*
97 fn dispatch(&mut self, mut b
: Buffer
<u8>) -> Buffer
<u8> {
98 let Dispatcher { handle_store, server }
= self;
100 let mut reader
= &b
[..];
101 match api_tags
::Method
::decode(&mut reader
, &mut ()) {
102 $
(api_tags
::Method
::$
name(m
) => match m
{
103 $
(api_tags
::$name
::$method
=> {
104 let mut call_method
= || {
105 reverse_decode
!(reader
, handle_store
; $
($arg
: $arg_ty
),*);
106 $name
::$
method(server
, $
($arg
),*)
108 // HACK(eddyb) don't use `panic::catch_unwind` in a panic.
109 // If client and server happen to use the same `libstd`,
110 // `catch_unwind` asserts that the panic counter was 0,
111 // even when the closure passed to it didn't panic.
112 let r
= if thread
::panicking() {
115 panic
::catch_unwind(panic
::AssertUnwindSafe(call_method
))
116 .map_err(PanicMessage
::from
)
120 r
.encode(&mut b
, handle_store
);
129 with_api
!(Self, self_
, define_dispatcher_impl
);
131 pub trait ExecutionStrategy
{
132 fn run_bridge_and_client
<D
: Copy
+ Send
+ '
static>(
134 dispatcher
: &mut impl DispatcherTrait
,
136 run_client
: extern "C" fn(Bridge
<'_
>, D
) -> Buffer
<u8>,
138 force_show_panics
: bool
,
142 pub struct SameThread
;
144 impl ExecutionStrategy
for SameThread
{
145 fn run_bridge_and_client
<D
: Copy
+ Send
+ '
static>(
147 dispatcher
: &mut impl DispatcherTrait
,
149 run_client
: extern "C" fn(Bridge
<'_
>, D
) -> Buffer
<u8>,
151 force_show_panics
: bool
,
153 let mut dispatch
= |b
| dispatcher
.dispatch(b
);
156 Bridge { cached_buffer: input, dispatch: (&mut dispatch).into(), force_show_panics }
,
162 // NOTE(eddyb) Two implementations are provided, the second one is a bit
163 // faster but neither is anywhere near as fast as same-thread execution.
165 pub struct CrossThread1
;
167 impl ExecutionStrategy
for CrossThread1
{
168 fn run_bridge_and_client
<D
: Copy
+ Send
+ '
static>(
170 dispatcher
: &mut impl DispatcherTrait
,
172 run_client
: extern "C" fn(Bridge
<'_
>, D
) -> Buffer
<u8>,
174 force_show_panics
: bool
,
176 use std
::sync
::mpsc
::channel
;
178 let (req_tx
, req_rx
) = channel();
179 let (res_tx
, res_rx
) = channel();
181 let join_handle
= thread
::spawn(move || {
182 let mut dispatch
= |b
| {
183 req_tx
.send(b
).unwrap();
184 res_rx
.recv().unwrap()
189 cached_buffer
: input
,
190 dispatch
: (&mut dispatch
).into(),
198 res_tx
.send(dispatcher
.dispatch(b
)).unwrap();
201 join_handle
.join().unwrap()
205 pub struct CrossThread2
;
207 impl ExecutionStrategy
for CrossThread2
{
208 fn run_bridge_and_client
<D
: Copy
+ Send
+ '
static>(
210 dispatcher
: &mut impl DispatcherTrait
,
212 run_client
: extern "C" fn(Bridge
<'_
>, D
) -> Buffer
<u8>,
214 force_show_panics
: bool
,
216 use std
::sync
::{Arc, Mutex}
;
223 let mut state
= Arc
::new(Mutex
::new(State
::Res(Buffer
::new())));
225 let server_thread
= thread
::current();
226 let state2
= state
.clone();
227 let join_handle
= thread
::spawn(move || {
228 let mut dispatch
= |b
| {
229 *state2
.lock().unwrap() = State
::Req(b
);
230 server_thread
.unpark();
233 if let State
::Res(b
) = &mut *state2
.lock().unwrap() {
241 cached_buffer
: input
,
242 dispatch
: (&mut dispatch
).into(),
248 // Wake up the server so it can exit the dispatch loop.
250 server_thread
.unpark();
255 // Check whether `state2` was dropped, to know when to stop.
256 while Arc
::get_mut(&mut state
).is_none() {
258 let mut b
= match &mut *state
.lock().unwrap() {
259 State
::Req(b
) => b
.take(),
262 b
= dispatcher
.dispatch(b
.take());
263 *state
.lock().unwrap() = State
::Res(b
);
264 join_handle
.thread().unpark();
267 join_handle
.join().unwrap()
273 I
: Encode
<HandleStore
<MarkedTypes
<S
>>>,
274 O
: for<'a
, 's
> DecodeMut
<'a
, 's
, HandleStore
<MarkedTypes
<S
>>>,
275 D
: Copy
+ Send
+ '
static,
277 strategy
: &impl ExecutionStrategy
,
278 handle_counters
: &'
static client
::HandleCounters
,
281 run_client
: extern "C" fn(Bridge
<'_
>, D
) -> Buffer
<u8>,
283 force_show_panics
: bool
,
284 ) -> Result
<O
, PanicMessage
> {
286 Dispatcher { handle_store: HandleStore::new(handle_counters), server: MarkedTypes(server) }
;
288 let mut b
= Buffer
::new();
289 input
.encode(&mut b
, &mut dispatcher
.handle_store
);
291 b
= strategy
.run_bridge_and_client(
299 Result
::decode(&mut &b
[..], &mut dispatcher
.handle_store
)
302 impl client
::Client
<fn(crate::TokenStream
) -> crate::TokenStream
> {
303 pub fn run
<S
: Server
>(
305 strategy
: &impl ExecutionStrategy
,
307 input
: S
::TokenStream
,
308 force_show_panics
: bool
,
309 ) -> Result
<S
::TokenStream
, PanicMessage
> {
310 let client
::Client { get_handle_counters, run, f }
= *self;
313 get_handle_counters(),
315 <MarkedTypes
<S
> as Types
>::TokenStream
::mark(input
),
320 .map(<MarkedTypes
<S
> as Types
>::TokenStream
::unmark
)
324 impl client
::Client
<fn(crate::TokenStream
, crate::TokenStream
) -> crate::TokenStream
> {
325 pub fn run
<S
: Server
>(
327 strategy
: &impl ExecutionStrategy
,
329 input
: S
::TokenStream
,
330 input2
: S
::TokenStream
,
331 force_show_panics
: bool
,
332 ) -> Result
<S
::TokenStream
, PanicMessage
> {
333 let client
::Client { get_handle_counters, run, f }
= *self;
336 get_handle_counters(),
339 <MarkedTypes
<S
> as Types
>::TokenStream
::mark(input
),
340 <MarkedTypes
<S
> as Types
>::TokenStream
::mark(input2
),
346 .map(<MarkedTypes
<S
> as Types
>::TokenStream
::unmark
)