On Wednesday, 9 October 2013 at 15:50:55 UTC, Daniel Davidson wrote:
void foo(const(MutableType) mt);
void foo(immutable(MutableType) mt);

Naturally the inclination is to choose the second as it is a stronger guarantee that no threads are changing the data. Cool. But wait, the first one still probably requires the same guarantee, even if it does not state it. If in the const case another thread changes the state of mt during the function foo then it will fail. foo actually requires that mt not be change by other threads during its operation - that is the only sane way of using the data in the function.

Why "the first one still probably requires the same guarantee"?
Why would foo fail if "in the const case another thread changes the state of mt"?
If foo is not thread-safe, then it should require immutable.

Take, for example, LinearCongruentialEngine from random.d. It has a function:

    bool opEquals(ref const LinearCongruentialEngine rhs) const

Why is it using const here instead of immutable? Does it not care about other threads? No - it just is not smart enough to deal with it. It assumes other threads won't be changing it or if they are caveat developer. So when do you use immutable as a signal that not only will this function not change it, no thread will change it either? Probably when you know you have to deal with threading. But that then would be coupling two maybe orthogonal decisions - the threading of a program and the signature of functions.

Hm, that actually looks like a bug. If LinearCongruentialEngine is instantiated with a UIntType larger than size_t, it is not thread-safe, but this seems to be claimed in the section header.

Why are those two decisions orthogonal? The signature of a function is a contract between caller and callee. If an argument is const, it means the callee says he can handle others changing the state concurrently.

Reply via email to