Description
This recent great blogpost said that AtomicCell
doesn't let the user choose the memory ordering, which is fair, but of course I had to immediately check which one it uses ;) . I was very surprised to see it use SeqCst
. I would have expected Acq
/Rel
/AcqRel
. This allows reasoning by ownership transfer, which is strong enough for almost everything.
I wouldn't usually care enough to actually submit an issue about this, but now I found this comment:
So AtomicCell is basically Mutex<Cell>, except faster. That's it.
This is not in the documentation as far as I can see, but I agree it makes sense as a principle. The thing is, from all I know it is perfectly legal to implement locks with release-acquire spinlocks, so by this argument, the accesses in AtomicCell
should definitely be release-acquire!
The post claims that
let x = AtomicCell::new(false);
let y = AtomicCell::new(false);
let z = AtomicCell::new(0usize);
scope(|s| {
s.spawn(|| x.store(true));
s.spawn(|| y.store(true));
s.spawn(|| {
while !x.load() {}
if y.load() { z.fetch_add(1); }
});
s.spawn(|| {
while !y.load() {}
if x.load() { z.fetch_add(1); }
});
}).unwrap();
assert!(z.load() > 0);
will pass when using Mutex<Cell>
, but (assuming this was tested) I think that is just an accident of the current implementation. Nothing in the C11 memory model requires this to pass when using locks, and you absolutely shouldn't rely on it.