2
2
3
3
use super :: * ;
4
4
5
+ use std:: cell:: Cell ;
5
6
use std:: marker:: PhantomData ;
6
7
7
8
macro_rules! define_handles {
@@ -256,7 +257,7 @@ macro_rules! define_client_side {
256
257
api_tags:: Method :: $name( api_tags:: $name:: $method) . encode( & mut b, & mut ( ) ) ;
257
258
reverse_encode!( b; $( $arg) ,* ) ;
258
259
259
- b = bridge. dispatch. call ( b) ;
260
+ b = ( bridge. dispatch) ( b) ;
260
261
261
262
let r = Result :: <_, PanicMessage >:: decode( & mut & b[ ..] , & mut ( ) ) ;
262
263
@@ -270,48 +271,64 @@ macro_rules! define_client_side {
270
271
}
271
272
with_api ! ( self , self , define_client_side) ;
272
273
273
- enum BridgeState < ' a > {
274
+ enum BridgeState {
274
275
/// No server is currently connected to this client.
275
276
NotConnected ,
276
277
277
278
/// A server is connected and available for requests.
278
- Connected ( Bridge < ' a > ) ,
279
+ Connected ( Bridge ) ,
279
280
280
281
/// Access to the bridge is being exclusively acquired
281
282
/// (e.g., during `BridgeState::with`).
282
283
InUse ,
283
284
}
284
285
285
- enum BridgeStateL { }
286
+ impl BridgeState {
287
+ /// Sets the thread-local `BridgeState` to `replacement` while
288
+ /// running `f`, which gets the old `BridgeState`, mutably.
289
+ ///
290
+ /// The state will be restored after `f` exits, even
291
+ /// by panic, including modifications made to it by `f`.
292
+ fn replace_during < R > ( replacement : Self , f : impl FnOnce ( & mut Self ) -> R ) -> R {
293
+ /// Wrapper that ensures that a cell always gets filled
294
+ /// (with the original state, optionally changed by `f`),
295
+ /// even if `f` had panicked.
296
+ struct PutBackOnDrop < ' a , T > {
297
+ cell : & ' a Cell < T > ,
298
+ value : Option < T > ,
299
+ }
286
300
287
- impl < ' a > scoped_cell:: ApplyL < ' a > for BridgeStateL {
288
- type Out = BridgeState < ' a > ;
289
- }
301
+ impl < ' a , T > Drop for PutBackOnDrop < ' a , T > {
302
+ fn drop ( & mut self ) {
303
+ self . cell . set ( self . value . take ( ) . unwrap ( ) ) ;
304
+ }
305
+ }
290
306
291
- thread_local ! {
292
- static BRIDGE_STATE : scoped_cell:: ScopedCell <BridgeStateL > =
293
- scoped_cell:: ScopedCell :: new( BridgeState :: NotConnected ) ;
294
- }
307
+ thread_local ! {
308
+ static BRIDGE_STATE : Cell <BridgeState > = Cell :: new( BridgeState :: NotConnected ) ;
309
+ }
310
+ BRIDGE_STATE . with ( |state| {
311
+ let mut put_back_on_drop =
312
+ PutBackOnDrop { cell : state, value : Some ( state. replace ( replacement) ) } ;
313
+
314
+ f ( put_back_on_drop. value . as_mut ( ) . unwrap ( ) )
315
+ } )
316
+ }
295
317
296
- impl BridgeState < ' _ > {
297
318
/// Take exclusive control of the thread-local
298
319
/// `BridgeState`, and pass it to `f`, mutably.
320
+ ///
299
321
/// The state will be restored after `f` exits, even
300
322
/// by panic, including modifications made to it by `f`.
301
323
///
302
324
/// N.B., while `f` is running, the thread-local state
303
325
/// is `BridgeState::InUse`.
304
- fn with < R > ( f : impl FnOnce ( & mut BridgeState < ' _ > ) -> R ) -> R {
305
- BRIDGE_STATE . with ( |state| {
306
- state. replace ( BridgeState :: InUse , |mut state| {
307
- // FIXME(#52812) pass `f` directly to `replace` when `RefMutL` is gone
308
- f ( & mut * state)
309
- } )
310
- } )
326
+ fn with < R > ( f : impl FnOnce ( & mut Self ) -> R ) -> R {
327
+ Self :: replace_during ( BridgeState :: InUse , f)
311
328
}
312
329
}
313
330
314
- impl Bridge < ' _ > {
331
+ impl Bridge {
315
332
pub ( crate ) fn is_available ( ) -> bool {
316
333
BridgeState :: with ( |state| match state {
317
334
BridgeState :: Connected ( _) | BridgeState :: InUse => true ,
@@ -337,10 +354,10 @@ impl Bridge<'_> {
337
354
} ) ) ;
338
355
} ) ;
339
356
340
- BRIDGE_STATE . with ( |state| state . set ( BridgeState :: Connected ( self ) , f ) )
357
+ BridgeState :: replace_during ( BridgeState :: Connected ( self ) , |_| f ( ) )
341
358
}
342
359
343
- fn with < R > ( f : impl FnOnce ( & mut Bridge < ' _ > ) -> R ) -> R {
360
+ fn with < R > ( f : impl FnOnce ( & mut Self ) -> R ) -> R {
344
361
BridgeState :: with ( |state| match state {
345
362
BridgeState :: NotConnected => {
346
363
panic ! ( "procedural macro API is used outside of a procedural macro" ) ;
@@ -367,15 +384,15 @@ pub struct Client<F> {
367
384
// FIXME(eddyb) use a reference to the `static COUNTERS`, instead of
368
385
// a wrapper `fn` pointer, once `const fn` can reference `static`s.
369
386
pub ( super ) get_handle_counters : extern "C" fn ( ) -> & ' static HandleCounters ,
370
- pub ( super ) run : extern "C" fn ( Bridge < ' _ > , F ) -> Buffer < u8 > ,
387
+ pub ( super ) run : extern "C" fn ( Bridge , F ) -> Buffer < u8 > ,
371
388
pub ( super ) f : F ,
372
389
}
373
390
374
391
/// Client-side helper for handling client panics, entering the bridge,
375
392
/// deserializing input and serializing output.
376
393
// FIXME(eddyb) maybe replace `Bridge::enter` with this?
377
394
fn run_client < A : for < ' a , ' s > DecodeMut < ' a , ' s , ( ) > , R : Encode < ( ) > > (
378
- mut bridge : Bridge < ' _ > ,
395
+ mut bridge : Bridge ,
379
396
f : impl FnOnce ( A ) -> R ,
380
397
) -> Buffer < u8 > {
381
398
// The initial `cached_buffer` contains the input.
@@ -418,7 +435,7 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
418
435
impl Client < fn ( crate :: TokenStream ) -> crate :: TokenStream > {
419
436
pub const fn expand1 ( f : fn ( crate :: TokenStream ) -> crate :: TokenStream ) -> Self {
420
437
extern "C" fn run (
421
- bridge : Bridge < ' _ > ,
438
+ bridge : Bridge ,
422
439
f : impl FnOnce ( crate :: TokenStream ) -> crate :: TokenStream ,
423
440
) -> Buffer < u8 > {
424
441
run_client ( bridge, |input| f ( crate :: TokenStream ( input) ) . 0 )
@@ -432,7 +449,7 @@ impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
432
449
f : fn ( crate :: TokenStream , crate :: TokenStream ) -> crate :: TokenStream ,
433
450
) -> Self {
434
451
extern "C" fn run (
435
- bridge : Bridge < ' _ > ,
452
+ bridge : Bridge ,
436
453
f : impl FnOnce ( crate :: TokenStream , crate :: TokenStream ) -> crate :: TokenStream ,
437
454
) -> Buffer < u8 > {
438
455
run_client ( bridge, |( input, input2) | {
0 commit comments