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.