On 2010-10-31 12:39:10 -0400, Andrei Alexandrescu
<[email protected]> said:
On 10/31/10 5:40 AM, Michel Fortin wrote:
I'm not opposed to the idea of ruling out arbitrary-cost postblits, but
I fear it might be futile. If std::string is any indication, COW doesn't
scale well with multithreading. There is a way to make COW efficient for
thread-local objects in the GC-heap, but that would require thread-local
GC heaps, and this has been ruled out in the design of 'shared' and
'immutable'.
D's approach to concurrency is predicated by distinguishing shared data
from unshared data statically (by means of the shared qualifier).
Yes, and that was a very good idea.
As such, unshared types can always use non-atomic reference count
manipulation in confidence that there is no undue sharing going on.
And it works, except in a destructor when that destructor is called by
the GC (because the GC can call a destructor from another thread). The
discussion of 4621 shows that the compiler can't detect the races that
might arise if you dereference a member in a destructor. If the
compiler could be made to prevent those races, all instances of bug
4624 would be caught at compile-time and you'd have to either:
1. use a shared reference counter with atomic operations (and possibly
cast your way around), or
2. restrict those structs to the stack and non-GC allocated memory.
That's the conclusion from the discussion of bug 4621. A third way
would be to make the GC call a destructor in the thread that owns the
memory block, but how should the GC determine which thread owns which
block? Is memory always owned by the thread that allocated it? And does
that mean the destructor will be postponed until that thread asks for a
new memory allocation? Perhaps that's what we should do.
--
Michel Fortin
[email protected]
http://michelf.com/