auto classes and finalizers
Regan Heath
regan at netwin.co.nz
Mon Apr 10 16:54:42 PDT 2006
On Mon, 10 Apr 2006 11:05:00 +0100, Bruno Medeiros
<brunodomedeirosATgmail at SPAM.com> wrote:
> Mike Capp wrote:
>> In article <e1bj4r$1gt$1 at digitaldaemon.com>, Bruno Medeiros says...
>>> Some ideas where discussed here, but I didn't think any were fruitful.
>>> Like:
>>> *Forcing all classes with destructors to be auto classes -> doesn't
>>> add any usefulness, instead just nuisances.
>> Hmm, yes. Like private/protected member access specifiers - what
>> usefulness do
>> they add? Or requiring a cast to assign from one type to another - sheer
>> nuisance!
>> cheers
>> Mike
>>
>
> Protection attributes and casts add usefulness (not gonna detail why).
> Forcing all classes with destructors to be auto classes, on the other
> hand, severily limits the usage of such classes. An auto class can not
> be a global, static, field, inout and out parameter. It must be bound to
> a function, and *cannot be a part of another data structure*. This
> latter restriction, as is, is unacceptable, no?
The suggestion I made assumed we could remove these restrictions. I'm not
sure whether that's true or not, if it is impossible can someone explain
to me why? I would be curious to know. It seems that if C++ can have
classes at module/file scope that have destructors why can't D. I have a
feeling it has something to do with how Walter has implemented it.. but
that _could_ change, if the reasons were strong enough, right?
If we assume (for the purposes of exploring the solution) that the
restrictions can be removed doesn't this idea make a lot of sense?
1. any class/module with a dtor must be 'auto'.
2. any class/module containing a reference to an 'auto' class/module must
be 'auto'.
3. The 'auto' keyword used here; "auto Foo f = new Foo();" is not
required, remove it.
4. A 'shared' keyword is used to indicate a shared 'auto' resource.
Rationale: if a class has cleanup to do, it must be done all the time, not
just sometimes and not selectively*. Therefore any class with cleanup to
do is 'auto' and any class containing an 'auto' member also has cleanup to
do, thus must be 'auto'.
(*) the exception to this rule is a member reference to a shared resource,
thus the 'shared' keyword.
The compiler can auto-generate dtors for classes containing 'auto' members
eg.
auto class File {
HANDLE h;
~this() { CloseHandle(h); }
}
auto class Foo {
File f;
/*auto generated dtor
~this() { delete f; }
}
If the user supplies a dtor, the compiler can simply append it's auto-dtor
to the end of that (I don't think deleting a reference twice is a
problem). In this way 'auto' propagates itself as required.
(In fact if you think about it, the keyword 'auto' isn't really even
required. It can be removed and the behaviour outlined above can simply be
implemented)
The shared keyword would prevent the automatic dtor from calling delete on
the shared reference. If that reference was the only 'auto' member it
would therefore prevent the class from being 'auto' itself. The user would
have to manage the shared resource manually, or rather, can rely on it
being deleted by the (one and only) non-shared reference to it, eg.
[file.d]
File a = new File("a.txt");
class Foo {
shared File foo;
this(File f) { foo = f; }
}
void main()
{
Foo f = new Foo(a);
}
The class 'Foo' is not auto, it has no dtor, the compiler does not
generate one, it's shared reference 'foo' is never deleted. The module
level reference 'a' is auto, an auto generated module level dtor will
delete it.
The classes affected by this idea are few, I'd say less than 20% (even
with 'auto' propagating up the class tree), the rest will have no dtor and
will simply be collected as normal by the GC, no dtor calls required.
As far as I can see there are no restrictions of use for this idea.
Classes will be the same as they are today, only they'll have
deterministic destruction where required. Assuming of course it can
actually be implemented.
Regan
More information about the Digitalmars-d
mailing list