Continuing discussion regarding clear() from thread "QtD is suspended" in digitalmars.D.announce.

On 09/17/2010 12:01 PM, Steven Schveighoffer wrote:
On Fri, 17 Sep 2010 12:39:06 -0400, Andrei Alexandrescu
<seewebsiteforem...@erdani.org> 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...

... or on the Internet :o).

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).

That's a great point. So we're in good shape: we leave the object in a well-defined state that allocates no resources and is distinguished from all valid states.

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...

Done.

I think clear() can be fixed if we remove the call to the constructor AND obliterate the vptr. In fact ideally we'd obliterate all vptrs of the object, which might be tricky. Ideas?


Andrei

Reply via email to