Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save orenbenkiki/6206863 to your computer and use it in GitHub Desktop.
Save orenbenkiki/6206863 to your computer and use it in GitHub Desktop.
/// Intern a string using the task local interner.
pub fn intern(burrowed: &str) -> Intern {
do local_data::get(KEY_ARC_INTERNER) |maybe_arc_interner| {
match maybe_arc_interner {
None => fail!("no task local ARC for global interner"),
Some(arc_interner) => {
// TRICKY: Only obtain a read lock for the common case
// where the string was previously interned.
do arc_interner.read |interner| {
match interner.str_to_intern.find(&burrowed.to_str()) {
Some(intern) => *intern,
None => {
// TRICKY: If we didn't find it above, we need
// to get a write lock and re-find it, to
// ensure no other task sneaked in and added it
// between the above find and obtaining the
// write lock below. This sort of race
// condition is why one shouldn't write code
// using locks unless it is *really* necessary.
//
// OOPS: This doesn't work because we are
// trying to get a write lock while (our!) read
// lock is in effect; so this deadlocks. There
// is no "write_upgrade"
do arc_interner.write |mut_interner: &mut Interner| {
let intern = do mut_interner.str_to_intern.find_or_insert_with(burrowed.to_str()) |owned| {
mut_interner.id_to_str.push(owned.clone());
Intern { id: mut_interner.id_to_str.len() - 1 }
};
*intern
}
}
}
}
}
}
}
}
/// Intern a string using the task local interner.
pub fn intern(burrowed: &str) -> Intern {
do local_data::get(KEY_ARC_INTERNER) |maybe_arc_interner| {
match maybe_arc_interner {
None => fail!("no task local ARC for global interner"),
Some(arc_interner) => {
// TRICKY: Only obtain a read lock for the common case
// where the string was previously interned.
//
// OOPS: The compiler can't deduce the lifetime of
// maybe_intern.
let maybe_intern = do arc_interner.read |interner| {
interner.str_to_intern.find(&burrowed.to_str())
};
match maybe_intern {
Some(intern) => *intern,
None => {
// TRICKY: If we didn't find it above, we need
// to get a write lock and re-find it, to
// ensure no other task sneaked in and added it
// between the above find and obtaining the
// write lock below. This sort of race
// condition is why one shouldn't write code
// using locks unless it is *really* necessary.
do arc_interner.write |mut_interner: &mut Interner| {
let intern = do mut_interner.str_to_intern.find_or_insert_with(burrowed.to_str()) |owned| {
mut_interner.id_to_str.push(owned.clone());
Intern { id: mut_interner.id_to_str.len() - 1 }
};
*intern
}
}
}
}
}
}
}
/// Intern a string using the task local interner.
pub fn intern(burrowed: &str) -> Intern {
do local_data::get(KEY_ARC_INTERNER) |maybe_arc_interner| {
match maybe_arc_interner {
None => fail!("no task local ARC for global interner"),
Some(arc_interner) => {
// TRICKY: Only obtain a read lock for the common case
// where the string was previously interned.
//
// OOPS: The compiler dies with an internal bug error...
let maybe_intern: &'self Option<&Intern> = do arc_interner.read |interner| {
interner.str_to_intern.find(&burrowed.to_str())
};
match maybe_intern {
Some(intern) => *intern,
None => {
// TRICKY: If we didn't find it above, we need
// to get a write lock and re-find it, to
// ensure no other task sneaked in and added it
// between the above find and obtaining the
// write lock below. This sort of race
// condition is why one shouldn't write code
// using locks unless it is *really* necessary.
do arc_interner.write |mut_interner: &mut Interner| {
let intern = do mut_interner.str_to_intern.find_or_insert_with(burrowed.to_str()) |owned| {
mut_interner.id_to_str.push(owned.clone());
Intern { id: mut_interner.id_to_str.len() - 1 }
};
*intern
}
}
}
}
}
}
}
oren@LinuxBox:~/Rust/workspace$ RUST_LOG=rustc=1,::rt::backtrace rust test src/anthill/crate.rs
task <unnamed> failed at 'assertion failed: rp.is_none()', /home/oren/Rust/rust/src/librustc/middle/typeck/collect.rs:1061
error: internal compiler error: unexpected failure
note: the compiler hit an unexpected failure path. this is a bug
note: try running with RUST_LOG=rustc=1,::rt::backtrace to get further details and report the results to github.com/mozilla/rust/issues
task <unnamed> failed at 'explicit failure', /home/oren/Rust/rust/src/librustc/rustc.rs:375
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment