@@ -115,25 +115,25 @@ pub struct ParallelGuard {
115
115
}
116
116
117
117
impl ParallelGuard {
118
- #[ inline]
119
- pub fn new ( ) -> Self {
120
- ParallelGuard { panic : Mutex :: new ( None ) }
121
- }
122
-
123
118
pub fn run < R > ( & self , f : impl FnOnce ( ) -> R ) -> Option < R > {
124
119
catch_unwind ( AssertUnwindSafe ( f) )
125
120
. map_err ( |err| {
126
121
* self . panic . lock ( ) = Some ( err) ;
127
122
} )
128
123
. ok ( )
129
124
}
125
+ }
130
126
131
- #[ inline]
132
- pub fn unwind ( self ) {
133
- if let Some ( panic) = self . panic . into_inner ( ) {
134
- resume_unwind ( panic) ;
135
- }
127
+ /// This gives access to a fresh parallel guard in the closure and will unwind any panics
128
+ /// caught in it after the closure returns.
129
+ #[ inline]
130
+ pub fn parallel_guard < R > ( f : impl FnOnce ( & ParallelGuard ) -> R ) -> R {
131
+ let guard = ParallelGuard { panic : Mutex :: new ( None ) } ;
132
+ let ret = f ( & guard) ;
133
+ if let Some ( panic) = guard. panic . into_inner ( ) {
134
+ resume_unwind ( panic) ;
136
135
}
136
+ ret
137
137
}
138
138
139
139
cfg_if ! {
@@ -231,38 +231,38 @@ cfg_if! {
231
231
where A : FnOnce ( ) -> RA ,
232
232
B : FnOnce ( ) -> RB
233
233
{
234
- let guard = ParallelGuard :: new( ) ;
235
- let a = guard. run( oper_a) ;
236
- let b = guard. run( oper_b) ;
237
- guard. unwind( ) ;
234
+ let ( a, b) = parallel_guard( |guard| {
235
+ let a = guard. run( oper_a) ;
236
+ let b = guard. run( oper_b) ;
237
+ ( a, b)
238
+ } ) ;
238
239
( a. unwrap( ) , b. unwrap( ) )
239
240
}
240
241
241
242
#[ macro_export]
242
243
macro_rules! parallel {
243
244
( $( $blocks: block) , * ) => { {
244
- let mut guard = $crate :: sync:: ParallelGuard :: new ( ) ;
245
- $( guard. run( || $blocks) ; ) *
246
- guard . unwind ( ) ;
245
+ $crate :: sync:: parallel_guard ( |guard| {
246
+ $( guard. run( || $blocks) ; ) *
247
+ } ) ;
247
248
} }
248
249
}
249
250
250
251
pub fn par_for_each_in<T : IntoIterator >( t: T , mut for_each: impl FnMut ( T :: Item ) + Sync + Send ) {
251
- let guard = ParallelGuard :: new ( ) ;
252
- t. into_iter( ) . for_each( |i| {
253
- guard. run( || for_each( i) ) ;
254
- } ) ;
255
- guard . unwind ( ) ;
252
+ parallel_guard ( | guard| {
253
+ t. into_iter( ) . for_each( |i| {
254
+ guard. run( || for_each( i) ) ;
255
+ } ) ;
256
+ } )
256
257
}
257
258
258
259
pub fn par_map<T : IntoIterator , R , C : FromIterator <R >>(
259
260
t: T ,
260
261
mut map: impl FnMut ( <<T as IntoIterator >:: IntoIter as Iterator >:: Item ) -> R ,
261
262
) -> C {
262
- let guard = ParallelGuard :: new( ) ;
263
- let r = t. into_iter( ) . filter_map( |i| guard. run( || map( i) ) ) . collect( ) ;
264
- guard. unwind( ) ;
265
- r
263
+ parallel_guard( |guard| {
264
+ t. into_iter( ) . filter_map( |i| guard. run( || map( i) ) ) . collect( )
265
+ } )
266
266
}
267
267
268
268
pub use std:: rc:: Rc as Lrc ;
@@ -382,10 +382,11 @@ cfg_if! {
382
382
let ( a, b) = rayon:: join( move || FromDyn :: from( oper_a. into_inner( ) ( ) ) , move || FromDyn :: from( oper_b. into_inner( ) ( ) ) ) ;
383
383
( a. into_inner( ) , b. into_inner( ) )
384
384
} else {
385
- let guard = ParallelGuard :: new( ) ;
386
- let a = guard. run( oper_a) ;
387
- let b = guard. run( oper_b) ;
388
- guard. unwind( ) ;
385
+ let ( a, b) = parallel_guard( |guard| {
386
+ let a = guard. run( oper_a) ;
387
+ let b = guard. run( oper_b) ;
388
+ ( a, b)
389
+ } ) ;
389
390
( a. unwrap( ) , b. unwrap( ) )
390
391
}
391
392
}
@@ -421,10 +422,10 @@ cfg_if! {
421
422
// of a single threaded rustc.
422
423
parallel!( impl $fblock [ ] [ $( $blocks) , * ] ) ;
423
424
} else {
424
- let guard = $crate :: sync:: ParallelGuard :: new ( ) ;
425
- guard. run( || $fblock) ;
426
- $( guard. run( || $blocks) ; ) *
427
- guard . unwind ( ) ;
425
+ $crate :: sync:: parallel_guard ( |guard| {
426
+ guard. run( || $fblock) ;
427
+ $( guard. run( || $blocks) ; ) *
428
+ } ) ;
428
429
}
429
430
} ;
430
431
}
@@ -435,20 +436,18 @@ cfg_if! {
435
436
t: T ,
436
437
for_each: impl Fn ( I ) + DynSync + DynSend
437
438
) {
438
- if mode:: is_dyn_thread_safe( ) {
439
- let for_each = FromDyn :: from( for_each) ;
440
- let guard = ParallelGuard :: new( ) ;
441
- t. into_par_iter( ) . for_each( |i| {
442
- guard. run( || for_each( i) ) ;
443
- } ) ;
444
- guard. unwind( ) ;
445
- } else {
446
- let guard = ParallelGuard :: new( ) ;
447
- t. into_iter( ) . for_each( |i| {
448
- guard. run( || for_each( i) ) ;
449
- } ) ;
450
- guard. unwind( ) ;
451
- }
439
+ parallel_guard( |guard| {
440
+ if mode:: is_dyn_thread_safe( ) {
441
+ let for_each = FromDyn :: from( for_each) ;
442
+ t. into_par_iter( ) . for_each( |i| {
443
+ guard. run( || for_each( i) ) ;
444
+ } ) ;
445
+ } else {
446
+ t. into_iter( ) . for_each( |i| {
447
+ guard. run( || for_each( i) ) ;
448
+ } ) ;
449
+ }
450
+ } ) ;
452
451
}
453
452
454
453
pub fn par_map<
@@ -460,18 +459,14 @@ cfg_if! {
460
459
t: T ,
461
460
map: impl Fn ( I ) -> R + DynSync + DynSend
462
461
) -> C {
463
- if mode:: is_dyn_thread_safe( ) {
464
- let map = FromDyn :: from( map) ;
465
- let guard = ParallelGuard :: new( ) ;
466
- let r = t. into_par_iter( ) . filter_map( |i| guard. run( || map( i) ) ) . collect( ) ;
467
- guard. unwind( ) ;
468
- r
469
- } else {
470
- let guard = ParallelGuard :: new( ) ;
471
- let r = t. into_iter( ) . filter_map( |i| guard. run( || map( i) ) ) . collect( ) ;
472
- guard. unwind( ) ;
473
- r
474
- }
462
+ parallel_guard( |guard| {
463
+ if mode:: is_dyn_thread_safe( ) {
464
+ let map = FromDyn :: from( map) ;
465
+ t. into_par_iter( ) . filter_map( |i| guard. run( || map( i) ) ) . collect( )
466
+ } else {
467
+ t. into_iter( ) . filter_map( |i| guard. run( || map( i) ) ) . collect( )
468
+ }
469
+ } )
475
470
}
476
471
477
472
/// This makes locks panic if they are already held.
0 commit comments