Skip to content

Instantly share code, notes, and snippets.

Created October 29, 2015 17:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/79722e9b6674232bc926 to your computer and use it in GitHub Desktop.
Save anonymous/79722e9b6674232bc926 to your computer and use it in GitHub Desktop.
Demo of a problem when panicking from within scoped_threadpool
#![cfg_attr(test, feature(catch_panic))]
extern crate scoped_threadpool;
use scoped_threadpool::Pool;
use std::sync::atomic::{AtomicUsize, Ordering};
// The representation invariant for PositivelyAtomic is that it is
// always a positive integer. When we drop it, we store zero in
// its value; but one should never observe that.
pub struct PositivelyAtomic(AtomicUsize);
impl Drop for PositivelyAtomic {
fn drop(&mut self) {
self.0.store(0, Ordering::Relaxed);
}
}
impl PositivelyAtomic {
pub fn new(x: usize) -> PositivelyAtomic {
assert!(x > 0);
PositivelyAtomic(AtomicUsize::new(x))
}
// Assuming the representation invariant holds, this should
// always return a positive value.
pub fn load(&self) -> usize {
self.0.load(Ordering::Relaxed)
}
pub fn cas(&self, old: usize, new: usize) -> usize {
assert!(new > 0);
self.0.compare_and_swap(old, new, Ordering::Relaxed)
}
}
#[test]
fn demo_stack_allocated() {
for _i in 0..100 {
let _p = ::std::thread::catch_panic(move || {
let p = PositivelyAtomic::new(1);
kernel(&p);
});
}
}
#[test]
fn demo_heap_allocated() {
for i in 0..100 {
let _p = ::std::thread::catch_panic(move || {
let mut v = Vec::with_capacity((i % 5)*1024 + i);
v.push(PositivelyAtomic::new(1));
kernel(&v[0]);
});
}
}
pub fn kernel(r: &PositivelyAtomic) {
// Create a threadpool holding 4 threads
let mut pool = Pool::new(4);
// Use the threads as scoped threads that can
// reference anything outside this closure
pool.scoped(|scope| {
// Create references to each element in the vector ...
for _ in 0..4 {
scope.execute(move || {
for _ in 0..100000 {
let v = r.load();
if v == 0 {
panic!("SAW ZERO");
}
let v_new = (v % 100) + 1;
if v != r.cas(v, v_new) {
// this is not a true panic condition
// in the original scenario.
//
// it rather is a rare event, and I want to
// emulate a rare panic occurring from one
// thread (and then see how the overall
// computation proceeds from there).
panic!("interference");
} else {
// incremented successfully
}
}
});
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment