On 25.09.2011 04:25, Peter Alexander wrote:
On 24/09/11 4:47 PM, Rainer Schuetze wrote:Sorry for the bad example, here's one that is not thread-safe, and where the invariant can fail in a multi-threaded environment: shared(int) globId; class C { invariant() { assert((globId & 1) == 0); } @property int id() immutable { globId = globId + 1; globId = globId + 1; return globId; } } But the details whether the operation happens to be thread safe or not is irrelevant, thread-safety is not guaranteed by the type system with immutable.It's still thread safe! I think you are misunderstanding what thread safety is. http://en.wikipedia.org/wiki/Thread_safety You are right in saying that the invariant may break, but that doesn't prove that the code isn't thread safe, it just proves that you have a bad invariant. You may as well have written: invariant() { assert(false); } and then claimed that the code wasn't thread safe because immutable didn't save you.
Grrr, another bad example, where some bad side-effects did not get unnoticed ;-)
Thread safety in your example simply means that calling id() 10 times from different threads will always result in globId == 20 at the end. This isn't guaranteed by many languages.
This is what I wanted to show: it is also not guaranteed in D. Checking the disassembly there is nothing atomic about the operations. Even ++globId does not use a locked increment.
Thread safety does *not* guarantee that your invariant will hold, because your invariant not only requires thread safety but mutually exclusive access to globId around calls to id(). I should point out that immutable has absolutely no bearing in your example. Having immutable methods in a class with no members means nothing! The thread-safety comes from the shared(int) here.
Which finally brings us back to the original question: What does immutable guarantee in the face of non-pure property getter functions?
