On Fri, 17 Sep 2010 12:39:06 -0400, Andrei Alexandrescu
<[email protected]> wrote:
On 09/17/2010 09:02 AM, Max Samukha wrote:
One example is the semantics of clear() and scoped(). As I understood
from one of your posts, you agree that resurrecting the destroyed object
by calling its default constructor is objectionable. However, no further
action followed. So we are at a loss whether you have a better solution,
are still thinking about one, don't have time to change the
implementation or don't want to change the thing because it is engraved
in TDPL. The same applies to 'scoped' moving the object.
Good point. Also, clear() has been a favorite topic on #d because it's
good evidence of my incompetence.
One bad decision does not mean incompetence unless you're in politics...
The intent of clear(obj) is rather simple. It's supposed to put obj in a
well-defined, destroyable state that does not allocate resources. It's
the type system's last-ditch effort to preserve safety while at the same
time releasing all object state.
Currently, clear() works incorrectly for classes, where it invokes the
default constructor. SVN doesn't assign the blame to me, but the
decision does originate in discussions I took part in. clear() shouldn't
call the default constructor of the class because then the class object
is free to allocate resources once again. What it should do is to blast
the default initializer for each field in the class. That's a
well-defined state that doesn't allocate resources - great.
There are two problems with that state. One, the state might fail the
invariant of the object, but that's expected - once you called clear(),
you leave an empty shell behind that's unusable unless you reseat
something into it.
Second, calling the destructor again from that state is problematic
(because of failing the invariant) and the GC calls the destructor. This
is also solvable: the GC might memcmp() the state of the object against
its default state. If comparison comes positive, the destructor is not
invoked. We need to be careful that doesn't impact collection times.
Slightly OT here, but memcmp isn't necessary. We have a couple easy tools
at our disposal. One I've suggested in the past -- zero out the vtable.
This makes a loud error if you try to use the object again (and I even
think Sean added stack traces to null pointer violations recently), plus
gives no access to the destructor (easily detectable by the GC).
The other I just thought of, each object memory block has a GC flag
(FINALIZE?) that indicates it should run a destructor. Just clear that
flag. This may need some optimization, I think at the moment you need to
take the GC lock.
If you want to continue this discussion, move to D newsgroup probably...
-Steve