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?

Reply via email to