On Thu, 04 Nov 2010 14:38:59 -0400, Andrei Alexandrescu <seewebsiteforem...@erdani.org> wrote:

Thanks to all for a very illuminating discussion. The dialog revealed that the topic of cheap copy construction is oddly linked with the topic of garbage collection: garbage collection calls destructors concurrently with other code, which means reference count code must be interlocked, which makes it not-so-cheap.

This is only a manifestation of a deeper problem: destructors can execute arbitrary code, and, if ran in an arbitrary thread, can cause all sorts of deadlocks and essentially render "shared" inoperant.

Walter and I discussed two possibilities this morning:

1. Never call class destructors (or never call them if more than one thread is running)

2. Each destructor should be called in the thread that created the object.

The second solution is quite attractive. It can be implemented by associating each thread with a worklist - a list of objects to destroy. The GC can run in any thread but it will not call destructors. Instead, it adds objects to be destroyed to the threads that created them (this means we need to add a field to each object with the thread ID of the creating thread). When client code calls new, the allocation routine will first inspect the worklist and call the destructors if needed.

I think this can be made to work and has good properties, although a fair amount of details need to be figured out. Please share any thoughts you may have.

What if a thread no longer exists? Would there be a way to mark such dtors that need this feature? I don't know, because it seems to me like a lot of band-aiding for something that is infrequently used (I've gotten along fine in D without reference counting for as long as I've used it).

You also need to provide a pointer in the object for a linked list for the work-list.

I'm thinking I would prefer to have the destructor and finalizer split, so the 'destructor' can tell whether it's being called synchronously or from the GC. Then the dtor itself can handle the whole worklist implementation.

I guess the only extra thing you would need in addition to that is a hook so memory allocation from a given thread can be hooked to process the worklist. Or maybe the worklist becomes a standard feature of the thread class, and you manually add the task from the destructor instead of the GC doing it for you.

-Steve

Reply via email to