On Wed, 11 Aug 2010 16:14:56 -0400, Don <nos...@nospam.com> wrote:

Michel Fortin wrote:
On 2010-08-11 15:09:45 -0400, Jonathan M Davis <jmdavisp...@gmail.com> said:

On Wednesday, August 11, 2010 11:33:54 Michel Fortin wrote:
I'm not too sure that'll work very well. I think a better solution
would be to have a way to distinguish between a struct that can be put
on the GC heap and one that cannot. A struct that cannot go on the GC
heap make it safe to access GC-managed members in its destructor, and
thus can have a @safe destructor.

But couldn't the fact that a struct has a destructor make it so that it can't be
declared anywhere but on the heap? The destructor itself could be what
distinguishes them. I don't see a need for any other @attributes or whatnot to
distinguish them.
Sure, and now you can't use std.containers.Array as a member in a Class, neither std.stdio.File, etc. Is there something left classes can do?

As far as I can tell, the use cases for finalizers are very limited. To me, destructors don't make any sense unless they are deterministic. For example, I think having a File class is probably a bug. You may be on a system which has no limit on the number of file handles, but generally, if you need resource management, you need a guarantee that the destructor will be called.

If a file handle is stored as part of a class, with a destructor that closes the file, the file might never get closed. So I don't think it's unreasonable to say that a struct with a destructor cannot be a member of a class.

So classes are not allowed to have open files? That's too limited. Deterministic closing of the file is still possible, just not guaranteed.

Here's the thing, we shouldn't be preventing smart people from writing useful code because we can't think of a way to make sure all idiot programmers close all their resources. Note also that a resource leak is not as damaging as memory corruption, which we have somewhat of an obligation to try and prevent idiots from doing.


Personally I think destructors should be restricted to structs and scope classes. I suspect that some form of registration with the gc could do the job of finalizers.

Destructor <=> deterministic destruction.

Destructors as they are now are too limited, because they cannot be sure they are being called by the GC or not, they must assume so. So in one sense I agree with you. But in another sense, we *still* need a way to clean up non-GC resources from GC-allocated items. Preventing GC allocated items from holding non-GC resources is a step in a very wrong direction.

I think any one of the proposals here that separates finalizers from destructors should be adequate. My backwards-compatible one is to pass a parameter to the destructor indicating whether it's being called deterministically or not, but that doesn't lend itself to preventing @safe finalizers. Michael also has one for using ~~this() and ~this(). We could designate a method that clear uses, like dispose() that deterministically disposes all resources. I don't really like the interface solution, because looking up an interface is expensive, plus clear is a template so it doesn't need to use interfaces.

Whatever gets decided, I don't think anything should prevent them from being GC allocated, it's just too limiting for useful code. The one initiative the compiler could take is to prevent writing a finalizer in @safe code, since that can lead to memory corruption.

-Steve

Reply via email to