As I was figuring out how to get started with loom, I wanted a way to ensure that a particular access does return multiple values. This made me feel more secure that I was using loom correctly. The solution I have below is a bit different than making assertions within the loom::model closure, because I can make claims about aggregates of all loom iterations, as opposed to making a claim about a single iteration.
The solution that I have below is what I ended up with (shown on the README example). Is there a better pattern for accomplishing this?
use loom::sync::Arc;
use loom::sync::atomic::AtomicUsize;
use loom::sync::atomic::Ordering::{Acquire, Release, Relaxed};
use loom::thread;
use std::collections::HashSet;
#[test]
fn seen_values() {
// Using std::sync instead of loom::sync b/c I don't care about permuting these... I think?
let seen_values = std::sync::Arc::new(std::sync::Mutex::new(HashSet::new()));
let seen_values_cloned = seen_values.clone();
loom::model(move || {
let num = Arc::new(AtomicUsize::new(0));
let ths: Vec<_> = (0..2)
.map(|_| {
let num = num.clone();
thread::spawn(move || {
let curr = num.load(Acquire);
num.store(curr + 1, Release);
})
})
.collect();
for th in ths {
th.join().unwrap();
}
seen_values_cloned.lock().unwrap().insert(num.load(Relaxed));
});
let expected: HashSet<usize> = [1, 2].iter().cloned().collect();
assert_eq!(*seen_values.lock().unwrap(), expected);
}
I don't know the architecture or future plans for loom so this suggestion might not fit, but one idea I had was: what if loom::model returned an iterator of the return value of each closure call? Then I could write something like this:
use loom::sync::Arc;
use loom::sync::atomic::AtomicUsize;
use loom::sync::atomic::Ordering::{Acquire, Release, Relaxed};
use loom::thread;
use std::collections::HashSet;
#[test]
fn seen_values() {
let seen_values = loom::model(move || {
let num = Arc::new(AtomicUsize::new(0));
let ths: Vec<_> = (0..2)
.map(|_| {
let num = num.clone();
thread::spawn(move || {
let curr = num.load(Acquire);
num.store(curr + 1, Release);
})
})
.collect();
for th in ths {
th.join().unwrap();
}
// The closure would need to be parameterized to return a user-chosen type
num.load(Relaxed)
}).collect::<HashSet<usize>>();
let expected: HashSet<usize> = [1, 2].iter().cloned().collect();
assert_eq!(seen_values, expected);
}
As I was figuring out how to get started with loom, I wanted a way to ensure that a particular access does return multiple values. This made me feel more secure that I was using loom correctly. The solution I have below is a bit different than making assertions within the
loom::model
closure, because I can make claims about aggregates of all loom iterations, as opposed to making a claim about a single iteration.The solution that I have below is what I ended up with (shown on the README example). Is there a better pattern for accomplishing this?
I don't know the architecture or future plans for loom so this suggestion might not fit, but one idea I had was: what if
loom::model
returned an iterator of the return value of each closure call? Then I could write something like this: