Jump to page: 1 27  
Page
Thread overview
real destructors
May 15, 2002
Sandor Hojtsy
May 15, 2002
Pavel Minayev
May 15, 2002
Russ Lewis
May 15, 2002
OddesE
May 15, 2002
Pavel Minayev
May 15, 2002
Walter
May 16, 2002
Matthew Wilson
May 16, 2002
Russ Lewis
May 16, 2002
Pavel Minayev
May 20, 2002
Keith Ray
May 15, 2002
Patrick Down
May 16, 2002
Sandor Hojtsy
May 24, 2002
anderson
May 24, 2002
Pavel Minayev
May 24, 2002
Martin M. Pedersen
May 24, 2002
Roberto Mariottini
May 24, 2002
C.R.Chafer
May 24, 2002
Roberto Mariottini
May 24, 2002
Sean L. Palmer
May 24, 2002
Pavel Minayev
May 28, 2002
Roberto Mariottini
May 28, 2002
Pavel Minayev
May 31, 2002
Walter
May 24, 2002
C.R.Chafer
May 27, 2002
Keith Ray
May 27, 2002
C.R.Chafer
May 27, 2002
Pavel Minayev
May 27, 2002
anderson
Jun 01, 2002
Walter
Jun 01, 2002
Sean L. Palmer
Jun 01, 2002
anderson
May 24, 2002
Pavel Minayev
May 24, 2002
Martin M. Pedersen
May 24, 2002
Pavel Minayev
May 24, 2002
Carlos
May 25, 2002
Pavel Minayev
May 28, 2002
Martin M. Pedersen
May 28, 2002
anderson
May 29, 2002
Pavel Minayev
May 29, 2002
Martin M. Pedersen
May 29, 2002
Pavel Minayev
Bracketing (depreciated - Re: real destructors)
May 31, 2002
anderson
May 31, 2002
C.R.Chafer
May 31, 2002
Walter
May 28, 2002
Roberto Mariottini
May 28, 2002
anderson
May 28, 2002
Pavel Minayev
May 28, 2002
anderson
May 29, 2002
Pavel Minayev
May 28, 2002
C.R.Chafer
May 28, 2002
anderson
May 29, 2002
OddesE
May 30, 2002
C.R.Chafer
Jun 01, 2002
Walter
May 26, 2002
OddesE
May 26, 2002
Pavel Minayev
May 28, 2002
Roberto Mariottini
May 28, 2002
Roberto Mariottini
May 29, 2002
OddesE
May 29, 2002
Pavel Minayev
May 27, 2002
Ben Cohen
May 28, 2002
Matthew Wilson
May 26, 2002
OddesE
May 24, 2002
anderson
May 24, 2002
Pavel Minayev
May 25, 2002
anderson
May 25, 2002
Pavel Minayev
May 25, 2002
anderson
May 15, 2002
You no longer need to manually release dynamically allocated memory. So no destructors anymore? Wrong! You have to release thousand other types of phisical and logical resources. This is considered very rare and unimportant. I would rather say it has a moderate chance and has the same priority than releasing memory. That is: essential and inevitable. You should not accept workarounds here.

I think having real and deterministic destructors does not conflict with the garbage collection concept. I propose the following solution:

The destructor should be called when an object is ready for garbage collection (ref. count is 0), not when it is actually collected. In this case you can release any resources in the destructor.

What use is a destructor called anywhere else? Any example for a useful destructor with the current garbage collection concept?

You could say this will be slow. Well only a few of the objects need destuction anyway.

Let's consider this code. It is beyond awful:

int fn()
{
  my_type1  my_obj1 = new my_obj1;
  my_type2  my_obj2 = new my_obj2;
  my_type3  my_obj3 = new my_obj3;
  try {
    try {
     try {
       whatever();
     } finally { my_obj3.close(); }
    } finally { my_obj2.release(); }
  } finally { my_obj1.destroy(); }
}

Ideas?

Sandor Hojtsy


May 15, 2002
"Sandor Hojtsy" <hojtsy@index.hu> wrote in message news:abttuj$1ak$1@digitaldaemon.com...

> The destructor should be called when an object is ready for garbage collection (ref. count is 0), not when it is actually collected. In this case you can release any resources in the destructor.

D garbage collector is not reference-counting. So, even if you nullify the reference, it'll take time for garbage collector to make a cycle and detect the null pointer.

> What use is a destructor called anywhere else? Any example for a useful destructor with the current garbage collection concept?

Yes. I use destructors in my WinD project. Since GC is run at least once, at the end of the program, you can be sure that all non-closed windows will be closed, all DCs, brushes and pens freed, etc.

By the way, the same applies to files. If you forget to close() the File, it will be closed from the destructor, as soon as GC will run.

> Let's consider this code. It is beyond awful:
>
> int fn()
> {
>   my_type1  my_obj1 = new my_obj1;
>   my_type2  my_obj2 = new my_obj2;
>   my_type3  my_obj3 = new my_obj3;
>   try {
>     try {
>      try {
>        whatever();
>      } finally { my_obj3.close(); }
>     } finally { my_obj2.release(); }
>   } finally { my_obj1.destroy(); }
> }
>
> Ideas?

Yep. Rewrite it as:

    try try try
    {
        whatever()
    }
    finally my_obj3.close();
    finally my_obj2.release();
    finally my_obj1.destroy();

=)




May 15, 2002
Pavel Minayev wrote:

> > What use is a destructor called anywhere else? Any example for a useful destructor with the current garbage collection concept?
>
> Yes. I use destructors in my WinD project. Since GC is run at least once, at the end of the program, you can be sure that all non-closed windows will be closed, all DCs, brushes and pens freed, etc.
>
> By the way, the same applies to files. If you forget to close() the File, it will be closed from the destructor, as soon as GC will run.

You still have the potential for (temporary) memory leaks, even if they are cleaned up eventually.  In Windows, you could get a LOT of allocated objects very quickly if the GC didn't get around to running soon enough.

It would be very useful for the OS to be able to send a message/signal to the program when memory ran low, asking it to run the GC.  In such an architecture, you wouldn't even need to schedule a regular GC run...whenever the OS detected a low memory condition, every program would get a "GC signal", and the various GC's would release whatever memory they were holding on to that wasn't needed.

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]


May 15, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3CE29345.44CEF1D7@deming-os.org...
> Pavel Minayev wrote:
>
> > > What use is a destructor called anywhere else? Any example for a
useful
> > > destructor with the current garbage collection concept?
> >
> > Yes. I use destructors in my WinD project. Since GC is run at least
once,
> > at the end of the program, you can be sure that all non-closed windows will be closed, all DCs, brushes and pens freed, etc.
> >
> > By the way, the same applies to files. If you forget to close() the File, it will be closed from the destructor, as soon as GC will run.
>
> You still have the potential for (temporary) memory leaks, even if they
are
> cleaned up eventually.  In Windows, you could get a LOT of allocated
objects
> very quickly if the GC didn't get around to running soon enough.
>
> It would be very useful for the OS to be able to send a message/signal to
the
> program when memory ran low, asking it to run the GC.  In such an architecture, you wouldn't even need to schedule a regular GC
run...whenever
> the OS detected a low memory condition, every program would get a "GC
signal",
> and the various GC's would release whatever memory they were holding on to that wasn't needed.
>
> --
> The Villagers are Online! villagersonline.com
>
> .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
> .[ (a version.of(English).(precise.more)) is(possible) ]
> ?[ you want.to(help(develop(it))) ]
>


Or better yet, make the OS able of doing garbage collection!

--
Stijn
OddesE_XYZ@hotmail.com
http://OddesE.cjb.net
_________________________________________________
Remove _XYZ from my address when replying by mail




May 15, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3CE29345.44CEF1D7@deming-os.org...

> You still have the potential for (temporary) memory leaks, even if they
are
> cleaned up eventually.  In Windows, you could get a LOT of allocated
objects
> very quickly if the GC didn't get around to running soon enough.

Yes, you are right. Nothing I can do much with, though - window handles are released when windows are closed, and DCs are deleted, but pens and brushes might be used somewhere else, and thus can't be disposed that easy.




May 15, 2002
"Pavel Minayev" <evilone@omen.ru> wrote in news:abu1gg$47v$1 @digitaldaemon.com:

> 
> Yep. Rewrite it as:
> 
>     try try try
>     {
>         whatever()
>     }
>     finally my_obj3.close();
>     finally my_obj2.release();
>     finally my_obj1.destroy();
> 

What might be a nice piece of syntactic sugar
that would be something like this.

try(File f("data.dat"),Foo b(12))
{
  f.read(...)// blah blah
}

which would be rewriten as:

try
{
  f = new File("data.dat");
  b = new Foo(12);

  f.read(...)//blah blah
}
finally
{
  delete b;
  delete f;
}


This deals with stack lifetime issues.

For object lifetime issues maybe a new keyword
"owned"

class Foo
{
  owned File f;
}

When Foo is deleted or collected the finalizer
goes through all the objects "owned" pointers and
deletes them.

May 15, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3CE29345.44CEF1D7@deming-os.org...
> You still have the potential for (temporary) memory leaks, even if they
are
> cleaned up eventually.  In Windows, you could get a LOT of allocated
objects
> very quickly if the GC didn't get around to running soon enough.

It's not that bad. Just use:

    f = new Foo();
    f.acquire_resource();
    f.operations();
    f.release_resource();

In the normal case, your resources get released. Only when an exception occurs does the release_resource() get skipped, but it still gets run some time later when the GC runs (if Foo is written right). If that isn't enough, just use try-finally.

>
> It would be very useful for the OS to be able to send a message/signal to
the
> program when memory ran low, asking it to run the GC.  In such an architecture, you wouldn't even need to schedule a regular GC
run...whenever
> the OS detected a low memory condition, every program would get a "GC
signal",
> and the various GC's would release whatever memory they were holding on to that wasn't needed.

Just execute:

    gc.fullCollect();


May 16, 2002
I have to say I strongly disagree with this strong coupling of object destruction/finalisation with memory garbage collection.

It is this very model that is one of the three big criticisms of Java, along with lack of out parameters (big thanks for putting that in D, Walter) and lack of const. Java could also do with templates, but one can forgive them for avoiding the difficulties in that case.

One of my friends is a major a Java guru, having worked in the inner circle at Sun for a long time, and he poo-poos my criticism of Java's denial of the so-useful-we-don't-even-think-about-it-any-more "resource acquisition is initialisation" idiom, and its built-in support in C++. However, it seems to me to be the most basic (fundamental, as well as easily understood) tenet of object-orientation that an object clears up after itself.

I have heard many times, from Java proponents, that finalisation eventuates and so resource cleanup is carried out, but isn't this like a naughty child who will clean up his room "later". The analogy is not as purile as it may seem, since in order to get, say, a .NET file stream to clear up after itself before disappearing out of scope, we have to call Close(), rather like making your child do the room tidy before going out for the evening. Seriously, if a file is locked and preventing another thread/process from accessing it, then this is a bug in any practical sense, despite the original locker begin guaranteed to unlock it sometime later.

The answere in Java & .NET is to pepper one's code with try/finally blocks. Wasn't part of the reason for the introduction of exception handling to reduce error-handling clutter obfuscating that actual task-specific code? Even the use of a using/scope block to enforce dtor/finalise call at the end of the scope is adding code.

Another criticism from Java/.NET proponents is that this is forcing an idiom on a lot of code that does not need/want it. This is not the case, since one could quite easily omit a definition of Finalise/~dtor, and presumably the runtime system can take advantage of this omission for the purposes of its internal efficiencies, only calling the destructor when explicitly there (or in a superordinate class). If we get them off the soap-box for a mo, however, we surely have to ask what is the point of defining a function that _may_ get called at some time in the future, or just as well may not?

We witness some acknowledgement of this horrible omission in Java in the C#/.NET implementation, although they provide the most gauche "solution" in their Dispose idiom: an utter load of nonsense.

If one doesn't need destruction, don't define a destructor. If one needs (deterministic) destruction, let's have it. If one wants non-deterministic destruction, I have to ask: what are you asking for? why do you want it? Hopefully someone can enlighten me.

I hope that D can avoid this coupling, and continue with what seems in all other regards to be a superb idea.

Matthew

"Walter" <walter@digitalmars.com> wrote in message news:<abunoi$o4u$1@digitaldaemon.com>...
>
> "Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3CE29345.44CEF1D7@deming-os.org...
> > You still have the potential for (temporary) memory leaks, even if they
> are
> > cleaned up eventually. In Windows, you could get a LOT of allocated
> objects
> > very quickly if the GC didn't get around to running soon enough.
>
> It's not that bad. Just use:
>
> f = new Foo();
> f.acquire_resource();
> f.operations();
> f.release_resource();
>
> In the normal case, your resources get released. Only when an exception occurs does the release_resource() get skipped, but it still gets run some time later when the GC runs (if Foo is written right). If that isn't
enough,
> just use try-finally.
>
> >
> > It would be very useful for the OS to be able to send a message/signal
to
> the
> > program when memory ran low, asking it to run the GC. In such an architecture, you wouldn't even need to schedule a regular GC
> run...whenever
> > the OS detected a low memory condition, every program would get a "GC
> signal",
> > and the various GC's would release whatever memory they were holding on
to
> > that wasn't needed.
>
> Just execute:
>
> gc.fullCollect();
>
>
"Walter" <walter@digitalmars.com> wrote in message news:abunoi$o4u$1@digitaldaemon.com...
>
> "Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3CE29345.44CEF1D7@deming-os.org...
> > You still have the potential for (temporary) memory leaks, even if they
> are
> > cleaned up eventually.  In Windows, you could get a LOT of allocated
> objects
> > very quickly if the GC didn't get around to running soon enough.
>
> It's not that bad. Just use:
>
>     f = new Foo();
>     f.acquire_resource();
>     f.operations();
>     f.release_resource();
>
> In the normal case, your resources get released. Only when an exception occurs does the release_resource() get skipped, but it still gets run some time later when the GC runs (if Foo is written right). If that isn't
enough,
> just use try-finally.
>
> >
> > It would be very useful for the OS to be able to send a message/signal
to
> the
> > program when memory ran low, asking it to run the GC.  In such an architecture, you wouldn't even need to schedule a regular GC
> run...whenever
> > the OS detected a low memory condition, every program would get a "GC
> signal",
> > and the various GC's would release whatever memory they were holding on
to
> > that wasn't needed.
>
> Just execute:
>
>     gc.fullCollect();
>
>


May 16, 2002
> > int fn()
> > {
> >   my_type1  my_obj1 = new my_obj1;
> >   my_type2  my_obj2 = new my_obj2;
> >   my_type3  my_obj3 = new my_obj3;
> >   try {
> >     try {
> >      try {
> >        whatever();
> >      } finally { my_obj3.close(); }
> >     } finally { my_obj2.release(); }
> >   } finally { my_obj1.destroy(); }
> > }
> >
> > Ideas?
>
> Yep. Rewrite it as:
>
>     try try try
>     {
>         whatever()
>     }
>     finally my_obj3.close();
>     finally my_obj2.release();
>     finally my_obj1.destroy();

I was interested if anyone will notice that correctly this is written as:

int fn()
{
   my_type1  my_obj1 = new my_obj1;
   try {
     my_type2  my_obj2 = new my_obj2;
     try {
       my_type3  my_obj3 = new my_obj3;
       try {
         whatever();
      } finally my_obj3.close();
    } finally my_obj2.release();
  } finally my_obj1.destroy();
}

I consider that noone has noticed this,
a sign of lack of understandability, and of difficult debugging.
I cannot think of any syntactic sugar that could help here.
It needs more fundamental changes.

Yours,
Sandor Hojtsy


May 16, 2002
Walter wrote:

> > It would be very useful for the OS to be able to send a message/signal to
> the
> > program when memory ran low, asking it to run the GC.  In such an architecture, you wouldn't even need to schedule a regular GC
> run...whenever
> > the OS detected a low memory condition, every program would get a "GC
> signal",
> > and the various GC's would release whatever memory they were holding on to that wasn't needed.
>
> Just execute:
>
>     gc.fullCollect();

I would also like to be able to register objects with the GC such that when fullCollect() is called, these objects get callbacks (before garbage collection runs).  The callback would allow the object to release any memory that it is holding but is not critical.

For instance, when I allocate & deallocate hundreds of little objects, I like to use a "pool class," which, in C++, is like this:

    template <class X> class Pool
    {
    protected:
        X *array;  // dynamically sized

    public:
        X *Get()
        {
            if(array_is_empty)
                return new Pool;
            else
                return remove_first_element_from_array;
        }
        void Put(X *ptr)
        {
            add_ptr_to_array;
        }
        void Flush(int count=0)
        {
            while(count_in_array > count)
                delete remove_first_element_from_array;
            reallocate_array_to_size_count
        }
}



When gc.fullCollect() is called, I would like the garbage collector to call
Flush(0) on all of my registered pool objects.

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]


« First   ‹ Prev
1 2 3 4 5 6 7