October 06, 2004
In article <cjslr3$1oav$1@digitaldaemon.com>, Walter says...
>
>Since all the program's memory gets handed back to the operating system at program exit regardless, there's not much point to even bothering running a gc pass at program exit.
>

I think running the destructors at exit is a good thing, because:

1. Destructors are very rare in D, so it should be cheap - proportional to number of sockets + files + semaphores, plus a few.

2. Memory does not need to be analyzed or freed, you only want to iterate
over blocks (in any order), calling ~this() if found.

3. User can always prevent this action, so code can be safe by default, optionally fast later (if desired):

:int main()
:{
:    Convoluted x = new Convoluted(...);
:    gc.disable(); // destructors foiled
:}

Kevin



October 06, 2004
Ben Hinkle wrote:
> "Stewart Gordon" <smjg_1998@yahoo.com> wrote in message
> news:cjum4c$g35$1@digitaldaemon.com...
<snip>
>> Then what on the face of the planet would the point of having gc_term?
> 
> Why the incredulous response? Did I offend you at some point? If so I
> apologize.
> Anyway, I did say "by default" meaning some compiler flag (eg,
> version=CollectGarbageOnExit) or startup switch or something could cause it
> to do a full-collect at exit.

I still don't get it.  Why would someone put in a call to gc_term if it isn't what's wanted?

If someone's main function ends with a gc_term call, then someone wants it to collect the garbage when it exits.  There's no point in having to tell it twice by specifying a version as well.

<snip>
>> Because the OS has absolutely no idea how to flush a cache held by the
>> application or a third-party library.
> 
> 
> Destructors in D are very very limited.  In particular if the cache uses
> GC-managed memory it can't be referenced in a destructor.
<snip>

Do you mean that if you have something like

    class CachcedFile {
        void[] cache;
        ...

        ~this() {
            flush();
        }
    }

then cache will already be an invalid reference by the time the destructor is called?  I'm not sure how that would be.

Stewart.
October 06, 2004
"Stewart Gordon" <smjg_1998@yahoo.com> wrote in message news:ck0dfe$20u2$1@digitaldaemon.com...
> Ben Hinkle wrote:
> > "Stewart Gordon" <smjg_1998@yahoo.com> wrote in message news:cjum4c$g35$1@digitaldaemon.com...
> <snip>
> >> Then what on the face of the planet would the point of having gc_term?
> >
> > Why the incredulous response? Did I offend you at some point? If so I
> > apologize.
> > Anyway, I did say "by default" meaning some compiler flag (eg,
> > version=CollectGarbageOnExit) or startup switch or something could cause
it
> > to do a full-collect at exit.
>
> I still don't get it.  Why would someone put in a call to gc_term if it isn't what's wanted?
>
> If someone's main function ends with a gc_term call, then someone wants it to collect the garbage when it exits.  There's no point in having to tell it twice by specifying a version as well.

That's a good point. The reason I said gc_term should do nothing was because Walter mentioned gc_term. I should have said something like "it should be optional to call gc_term at program exit". I was being too imprecise by saying "gc_term should do nothing by default". There is a slight difference that I was ignoring.

> <snip>
> >> Because the OS has absolutely no idea how to flush a cache held by the application or a third-party library.
> >
> >
> > Destructors in D are very very limited.  In particular if the cache uses GC-managed memory it can't be referenced in a destructor.
> <snip>
>
> Do you mean that if you have something like
>
>      class CachcedFile {
>          void[] cache;
>          ...
>
>          ~this() {
>              flush();
>          }
>      }
>
> then cache will already be an invalid reference by the time the destructor is called?  I'm not sure how that would be.

Assuming the cache was allocated from the GC the flush() function shouldn't
reference it. The reason is that the collector collects memory in random
order so the destructor for a CachedFile might run after the cache has been
collected. The only things that should be referenced in a destructor are the
object itself and any external (non-GC managed) objects. Since most external
objects get cleaned up by the OS at exit anyway this tends to mean
destructors aren't very useful.
However, if the user explicitly calls "delete" then the destructor is called
directly so it is perfectly safe in that case for flush() to reference
cache. Perhaps the way to solve these problems is for the destructor to get
a parameter that says if the call was explicit or implicit:
 ~this(bool explicit) {
    if (explicit) flush();
  }

>
> Stewart.


October 06, 2004
Ben Hinkle wrote:

<snip>
> Assuming the cache was allocated from the GC the flush() function shouldn't
> reference it. The reason is that the collector collects memory in random
> order so the destructor for a CachedFile might run after the cache has been
> collected.

Collection and destruction don't have to happen at the same time. Indeed, the GC ought to run all the destructors it has to run, and then do the collecting.

Presumably, allocating more memory in a destructor is something you'd avoid anyway, whether or not it's supposed to persist after the destructor has run.

<snip>
> However, if the user explicitly calls "delete" then the destructor is called
> directly so it is perfectly safe in that case for flush() to reference
> cache. Perhaps the way to solve these problems is for the destructor to get
> a parameter that says if the call was explicit or implicit:
>  ~this(bool explicit) {
>     if (explicit) flush();
>   }

Thereby bringing in the horror from Fortran I thought we were trying to avoid.

Stewart.
October 06, 2004
"Stewart Gordon" <smjg_1998@yahoo.com> wrote in message news:ck0usl$2ft4$1@digitaldaemon.com...
> Ben Hinkle wrote:
>
> <snip>
> > Assuming the cache was allocated from the GC the flush() function
shouldn't
> > reference it. The reason is that the collector collects memory in random order so the destructor for a CachedFile might run after the cache has
been
> > collected.
>
> Collection and destruction don't have to happen at the same time. Indeed, the GC ought to run all the destructors it has to run, and then do the collecting.
>
> Presumably, allocating more memory in a destructor is something you'd avoid anyway, whether or not it's supposed to persist after the destructor has run.

For a mark-sweep collector that would be possible but for a generational collector it would have to make a full pass in order to call all the destructors before collecting anything (and that wouldn't be very generational). So to keep the GC implementation flexible the spec pretty much needs to say any garbage can be collected at any time (or never), in any order and on any thread.

> <snip>
> > However, if the user explicitly calls "delete" then the destructor is
called
> > directly so it is perfectly safe in that case for flush() to reference cache. Perhaps the way to solve these problems is for the destructor to
get
> > a parameter that says if the call was explicit or implicit:
> >  ~this(bool explicit) {
> >     if (explicit) flush();
> >   }
>
> Thereby bringing in the horror from Fortran I thought we were trying to avoid.

.I'm not familiar with the horror you are referring to - can you elaborate?


October 07, 2004
Ben Hinkle wrote:

<snip>
> For a mark-sweep collector that would be possible but for a generational
> collector it would have to make a full pass in order to call all the
> destructors before collecting anything (and that wouldn't be very
> generational). So to keep the GC implementation flexible the spec pretty
> much needs to say any garbage can be collected at any time (or never), in
> any order and on any thread.

Can you think of any scenario in which a two-pass mechanism (one to destruct, one to collect) wouldn't be possible?

<snip>
>>>a parameter that says if the call was explicit or implicit:
>>> ~this(bool explicit) {
>>>    if (explicit) flush();
>>>  }
>>
>>Thereby bringing in the horror from Fortran I thought we were trying to
>>avoid.
> 
> .I'm not familiar with the horror you are referring to - can you elaborate?

Open a file.  Write lots of data to it.  Then do any of the following:

- simply forget to close it
- interrupt the program (I'm not sure to what extent D manages to deal with this)
- exit via an error condition

The file is left incomplete, even more than it would be by the interruption/error alone.

Stewart.
1 2 3
Next ›   Last »