crystal clear()

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Fri Sep 17 14:33:11 PDT 2010


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
> <SeeWebsiteForEmail at 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


More information about the Digitalmars-d mailing list