Skip to content

Commit

Permalink
Execute all parallel blocks even if they panic in a single-threaded c…
Browse files Browse the repository at this point in the history
…ompiler
  • Loading branch information
Zoxc committed Mar 6, 2019
1 parent 01f7450 commit 7cc7b8f
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 5 deletions.
8 changes: 4 additions & 4 deletions src/librustc/hir/mod.rs
Expand Up @@ -30,7 +30,7 @@ use syntax::util::parser::ExprPrecedence;
use crate::ty::AdtKind;
use crate::ty::query::Providers;

use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync};
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
use rustc_data_structures::thin_vec::ThinVec;

use serialize::{self, Encoder, Encodable, Decoder, Decodable};
Expand Down Expand Up @@ -782,15 +782,15 @@ impl Crate {
where V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send
{
parallel!({
par_iter(&self.items).for_each(|(_, item)| {
par_for_each_in(&self.items, |(_, item)| {
visitor.visit_item(item);
});
}, {
par_iter(&self.trait_items).for_each(|(_, trait_item)| {
par_for_each_in(&self.trait_items, |(_, trait_item)| {
visitor.visit_trait_item(trait_item);
});
}, {
par_iter(&self.impl_items).for_each(|(_, impl_item)| {
par_for_each_in(&self.impl_items, |(_, impl_item)| {
visitor.visit_impl_item(impl_item);
});
});
Expand Down
42 changes: 41 additions & 1 deletion src/librustc_data_structures/sync.rs
Expand Up @@ -65,6 +65,7 @@ cfg_if! {
}

use std::ops::Add;
use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe};

#[derive(Debug)]
pub struct Atomic<T: Copy>(Cell<T>);
Expand Down Expand Up @@ -130,7 +131,19 @@ cfg_if! {
#[macro_export]
macro_rules! parallel {
($($blocks:tt),*) => {
$($blocks)*;
let mut panic = None;
$(
if let Err(p) = ::std::panic::catch_unwind(
::std::panic::AssertUnwindSafe(|| $blocks)
) {
if panic.is_none() {
panic = Some(p);
}
}
)*
if let Some(panic) = panic {
::std::panic::resume_unwind(panic);
}
}
}

Expand All @@ -140,6 +153,24 @@ cfg_if! {
t.into_iter()
}

pub fn par_for_each_in<T: IntoIterator>(
t: T,
for_each:
impl Fn(<<T as IntoIterator>::IntoIter as Iterator>::Item) + Sync + Send
) {
let mut panic = None;
t.into_iter().for_each(|i| {
if let Err(p) = catch_unwind(AssertUnwindSafe(|| for_each(i))) {
if panic.is_none() {
panic = Some(p);
}
}
});
if let Some(panic) = panic {
resume_unwind(panic);
}
}

pub type MetadataRef = OwningRef<Box<dyn Erased>, [u8]>;

pub use std::rc::Rc as Lrc;
Expand Down Expand Up @@ -308,6 +339,15 @@ cfg_if! {
t.into_par_iter()
}

pub fn par_for_each_in<T: IntoParallelIterator>(
t: T,
for_each: impl Fn(
<<T as IntoParallelIterator>::Iter as ParallelIterator>::Item
) + Sync + Send
) {
t.into_par_iter().for_each(for_each)
}

pub type MetadataRef = OwningRef<Box<dyn Erased + Send + Sync>, [u8]>;

/// This makes locks panic if they are already held.
Expand Down

0 comments on commit 7cc7b8f

Please sign in to comment.