 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Hyman Rosen Guest
|
Posted: Thu Jul 07, 2005 12:28 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Peter Dimov wrote:
| Quote: | 1. A thread calls release_resource, which grabs a lock.
2. The process returns from main. Everything is nuked.
3. A finalizer calls release_resource and blocks forever.
|
If "everything is nuked" then the original grabbing thread
is no longer holding the lock. Or else what does "nuked"
mean?
| Quote: | Finalizers shall never run on exit;
|
You're starting to sound like that other guy. So tell me
what happens in an ordinary C++ program under the following
circumstances?
1. A thread calls release_resource, which grabs a lock.
2. The process returns from main. Everything is nuked.
3. A static destructor calls in a singleton class calls
release_resource and blocks forever.
| Quote: | process termination releases all finalizable resources anyway.
|
One example I never tire of repeating is to use finalizers to
remove temp files.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Sergey P. Derevyago Guest
|
Posted: Thu Jul 07, 2005 2:40 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Hyman Rosen wrote:
| Quote: | Having said this, your "finalizers" are not finalizers in common sense.
Please give them some other name to prevent the confusion.
No. The Boehm collector does finalizers in a similar way, for example.
It was my recollection of those finalizers that led me to the scheme I
am describing. You will need to overcome your confusion without my
changing nomenclature.
See <http://www.hpl.hp.com/personal/Hans_Boehm/gc/finalization.html>.
As far as I can see from the description above, gc_cleanup ensures that the |
object being finalized *is* accessible to the finalizer...
--
With all respect, Sergey. http://ders.angen.net/
mailto : ders at skeptik.net
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gerhard Menzl Guest
|
Posted: Thu Jul 07, 2005 2:41 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Hyman Rosen wrote:
| Quote: | Ask yourself what it means for a program to request exit. What happens
to threads that are running? My view is that in some fashion, threads
stop executing in an orderly manner, leaving program state consistent.
If that is not the case, then nothing can be said about what happens
during exit. Now, once they have stopped executing, the collector can
designate only those objects reachable from finalizers as reachable.
Then it collects what it can, calls finalizers on collected objects if
present, and repeats until no more objects can be collected.
Presumably we may want to forbid finalizers from starting more
threads, but that's a detail.
|
I was using the term "termination" in the sense of resource clean-up, an
abstraction that covers both destruction and finalization. Sorry for the
confusion.
| Quote: | Because finalizers are used to clean up resources, not objects, and it
is far less likely for resources to depend on other resources than for
objects to depend on other objects. Most finalizers will simply
squirrel away some magic cookie like a file descriptor and just call a
function on it when finalizing.
|
Even if inter-resource dependency is less likely, this does not mean you
can ignore the issue. I don't know what kind of programs you write, but
in my experience it is not sufficient to deal with most or the more
likely cases.
| Quote: | I actually have no experience in this. I'm blue-skying the whole
thing.
|
Oh.
| Quote: | Of course not, but I believe it's doable in a reasonably good way
that, one, will do most of what people need, and two, will not cause
the weird paradoxes that caused Java's version to be deprecated. Let
me summarize the key parts
of what I see as the proper way:
0) Finalizers are called only for inaccessible objects (of course!)
1) Finalizers are separate objects from the objects they finalize.
2) The object being finalized is not accessible to the finalizer.
3) Finalizers are accessible until they complete.
4) Once program termination is requested and user threads have
stopped, a final collection phase can run remaining finalizers if
requested.
|
Now it is up to me to be confused. Call me dim or pedantic, but I find
the statements
1. Finalizers clean up resources, not objects.
2. Finalizers are objects that finalize other objects.
3. Objects being finalized are not accessible to their finalizers.
rather contradictory. Is there a difference between "clean up" and
"finalize"? If so, what is it, and if not so, how do you reconcile 1.
and 2.? And how can a finalizer finalize an object to which it has no
access?
--
Gerhard Menzl
#dogma int main ()
Humans may reply by replacing the thermal post part of my e-mail address
with "kapsch" and the top level domain part with "net".
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Peter Dimov Guest
|
Posted: Thu Jul 07, 2005 2:49 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Hyman Rosen wrote:
| Quote: | Peter Dimov wrote:
This isn't always true. When the process exits, all threads are
terminated. It's only dangerous to terminate some threads and leave
others running and potentially deadlocked, but stopping all threads
at once is safe.
If you posit this, notice that you cannot do deterministic cleanup
either. What of functions registered with atexit, or destructors of
static objects? Since those exist, there must be some sense of clean
program state when exiting, and finalizers will have the same context.
(Just "stopping threads" is insufficient. What if some thread is in
the middle of calling operator new, for example, and the allocator is
in an inconsistent state when the thread is stopped?)
|
Why does the above mean that a global setting of implicitly running
finalizers on exit is a good idea?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Fri Jul 08, 2005 12:44 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Sergey P. Derevyago wrote:
| Quote: | As far as I can see from the description above, gc_cleanup ensures that the
object being finalized *is* accessible to the finalizer...
|
Yes. I didn't say that my scheme was identical to the Boehm one.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Fri Jul 08, 2005 12:44 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Gerhard Menzl wrote:
| Quote: | Even if inter-resource dependency is less likely, this does not mean you
can ignore the issue. I don't know what kind of programs you write, but
in my experience it is not sufficient to deal with most or the more
likely cases.
|
If you have inter-resource depenedncy, then you handle it.
I never said that you can ignore the issue. I did say that
inter-resource dependency is less likely than inter-object
dependency. But if you have such a dependency, why is
dealing with it in finalizers any different from dealing
with it in deterministic cleanup?
| Quote: | Now it is up to me to be confused. Call me dim or pedantic, but I find
the statements
1. Finalizers clean up resources, not objects.
2. Finalizers are objects that finalize other objects.
3. Objects being finalized are not accessible to their finalizers.
rather contradictory. Is there a difference between "clean up" and
"finalize"? If so, what is it, and if not so, how do you reconcile 1.
and 2.? And how can a finalizer finalize an object to which it has no
access?
|
When I speak of finalizing an object, I mean "when the collector has
determined that a piece of allocated memory is inaccessible, and that
memory has a finalizer registered to it, invoke the finalizer". The
finalizer code then has a job to do, which is what I refer to as the
"clean up". This will generally involve releasing some resource. It
might close a file descriptor, or delete a temp file.
The finalizer does not need access to the object which the collector
has reclaimed because at the time the finalizer is registered it is
given a copy of the resource which it will eventually deal with. So
it may have a local integer member holding a file descriptor, or a
local string holding a file name.
Finalizers are scheduled actions. Their semantics are "when this object
becomes inaccessible, perform that action". Thus they do not need access
to the object, and denying them such access greatly simplifies the process
of dealing with memory reclamation.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Fri Jul 08, 2005 12:45 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Peter Dimov wrote:
| Quote: | Why does the above mean that a global setting of implicitly running
finalizers on exit is a good idea?
|
It doesn't. It means that doing so is no more harmful or difficult
than running atexit functions and destructors of singletons and
statics.
Whether to run finalizers on exit for a particular program is going
to be a decision made by the programmer, based on the nature of what
needs cleaning up.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Branimir Maksimovic Guest
|
Posted: Fri Jul 08, 2005 12:59 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Sergey P. Derevyago wrote:
| Quote: | Hyman Rosen wrote:
Having said this, your "finalizers" are not finalizers in common sense.
Please give them some other name to prevent the confusion.
No. The Boehm collector does finalizers in a similar way, for example.
It was my recollection of those finalizers that led me to the scheme I
am describing. You will need to overcome your confusion without my
changing nomenclature.
See <http://www.hpl.hp.com/personal/Hans_Boehm/gc/finalization.html>.
As far as I can see from the description above, gc_cleanup ensures that the
object being finalized *is* accessible to the finalizer...
|
That's just a one of ways one can use finalizers.
Actually I don't even include those c++ classes, rather write
my own that are similar with Hyman's proposal.
Good thing with Boehm's collector is that one can implement
different schemes. If you look more thoroughly finalizers are just
plain functions that are tied to some user data. That's similar to
what Hyman describes. gc_cleanup is class that passes "this" in special
form (as offset to begining of mem block) as user data and calls
destructor
, but one don't have to do that( or use that class).
Greetings, Bane.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Peter Dimov Guest
|
Posted: Fri Jul 08, 2005 1:12 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Hyman Rosen wrote:
| Quote: | Peter Dimov wrote:
1. A thread calls release_resource, which grabs a lock.
2. The process returns from main. Everything is nuked.
3. A finalizer calls release_resource and blocks forever.
If "everything is nuked" then the original grabbing thread
is no longer holding the lock. Or else what does "nuked"
mean?
|
The process, including all threads, is terminated. Whether the lock
held by the original thread remains locked would probably be
implementation defined.
| Quote: | Finalizers shall never run on exit;
You're starting to sound like that other guy. So tell me
what happens in an ordinary C++ program under the following
circumstances?
1. A thread calls release_resource, which grabs a lock.
2. The process returns from main. Everything is nuked.
3. A static destructor calls in a singleton class calls
release_resource and blocks forever.
|
Interesting question, thank you. What appears to happen on my platform
is that the "everything is nuked" part occurs _after_ the static
destructors are called.
| Quote: | process termination releases all finalizable resources anyway.
One example I never tire of repeating is to use finalizers to
remove temp files.
|
OK, let's accept the desire to remove temp files as the motivating
example to run finalizers on exit. Under your model, do finalizers
always run on exit? Do they run before or after the nuke? And if
running them on exit is optional, how could someone write code that
relies on a finalizer being invoked (to remove the temp file)?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
David J. Littleboy Guest
|
Posted: Fri Jul 08, 2005 10:18 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
"Hyman Rosen" <hyrosen (AT) mail (DOT) com> wrote:
| Quote: |
When I speak of finalizing an object, I mean "when the collector has
determined that a piece of allocated memory is inaccessible, and that
memory has a finalizer registered to it, invoke the finalizer". The
finalizer code then has a job to do, which is what I refer to as the
"clean up". This will generally involve releasing some resource. It
might close a file descriptor, or delete a temp file.
|
Hmm. It strikes me that using something that happens at GC time to close a
file descriptor or delete a temp file is seriously bletcherous. Not only do
you not know when that will happen, you don't even know if it will happen.
If the program exits before the GC runs, the files don't get closed.
| Quote: | From a long-term Lisp user's perspective, GC is for (freeing the programmer
from worrying about and) cleaning up bits of data structure that are no |
longer needed. The C++ concept of binding file descriptors and temp files to
objects and having the destructor clean up the files when the object is
either explicitly freed or implicitly freed by block exit (RAII) is
something that really can't be done by a GC-based memory management scheme.
So I think a lot of this thread is barking up the wrong tree.
David J. Littleboy
Tokyo, Japan
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Sergey P. Derevyago Guest
|
Posted: Fri Jul 08, 2005 11:13 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Hyman Rosen wrote:
| Quote: | As far as I can see from the description above, gc_cleanup ensures that the
object being finalized *is* accessible to the finalizer...
Yes. I didn't say that my scheme was identical to the Boehm one.
Well, here is the thread: |
-----------------------------------8<-----------------------------------
Hyman Rosen wrote:
2) The object being finalized is not accessible to the finalizer.
Sergey P. Derevyago wrote:
Having said this, your "finalizers" are not finalizers in common sense.
Please give them some other name to prevent the confusion.
Hyman Rosen wrote:
No. The Boehm collector does finalizers in a similar way, for example.
Sergey P. Derevyago wrote:
As far as I can see from the description above, gc_cleanup ensures that the
object being finalized *is* accessible to the finalizer...
Hyman Rosen wrote:
Yes. I didn't say that my scheme was identical to the Boehm one.
-----------------------------------8<-----------------------------------
IMHO I see the contradiction.
I believe, the "finalizers" you're working on aren't well defined.
--
With all respect, Sergey. http://ders.angen.net/
mailto : ders at skeptik.net
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gerhard Menzl Guest
|
Posted: Fri Jul 08, 2005 11:16 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Hyman Rosen wrote:
| Quote: | If you have inter-resource depenedncy, then you handle it.
I never said that you can ignore the issue. I did say that
inter-resource dependency is less likely than inter-object
dependency. But if you have such a dependency, why is
dealing with it in finalizers any different from dealing
with it in deterministic cleanup?
|
I'm having a déjà-vu here ...
Because it is non-deterministic and I cannot rely on the finalizers
releasing the resources in the required order, unless your concept
allows you to express dependencies between finalizers. Judging from your
descriptions, finalizers are pretty isolated pieces of code that don't
know each other. Am I wrong?
--
Gerhard Menzl
#dogma int main ()
Humans may reply by replacing the thermal post part of my e-mail address
with "kapsch" and the top level domain part with "net".
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Peter Dimov Guest
|
Posted: Fri Jul 08, 2005 1:21 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Hyman Rosen wrote:
| Quote: | Peter Dimov wrote:
Why does the above mean that a global setting of implicitly running
finalizers on exit is a good idea?
It doesn't. It means that doing so is no more harmful or difficult
than running atexit functions and destructors of singletons and
statics.
|
There are two cases:
1. You run the finalizers in a separate thread while the program threads are
still running.
Since the finalizer holds a copy of the resource, you run into the obvious
problem of releasing the resource while the live object is still using it.
For a resource that is as thread safe as an int, this invokes undefined
behavior.
2. You terminate all threads and then run the finalizers.
This leaves the program (including the resources) in an inconsistent state,
which means that it isn't possible to release the resources safely.
Singletons do have a similar problem if you attempt to destroy them while
the program is alive, which is why we don't.
The only safe way (that I see) to run finalizers on exit is to cancel all
threads, drop all references to all objects, then force a garbage collection
just before exit.
| Quote: | Whether to run finalizers on exit for a particular program is going
to be a decision made by the programmer, based on the nature of what
needs cleaning up.
|
Impossible in general if there is more than one programmer or the program
uses third-party libraries.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Sergey P. Derevyago Guest
|
Posted: Fri Jul 08, 2005 2:59 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Peter Dimov wrote:
| Quote: | The only safe way (that I see) to run finalizers on exit is to cancel all
threads, drop all references to all objects, then force a garbage collection
just before exit.
Well, the following really safe way is having been used for decades: |
1. Inform all threads to exit gracefully and clean up their thread local
resources.
2. Clean up global resources in the last (usually main) thread.
3. Exit application.
Personally, I see no need for any "nearly useful" features like finalizers on
exit...
--
With all respect, Sergey. http://ders.angen.net/
mailto : ders at skeptik.net
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Fri Jul 08, 2005 3:01 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Peter Dimov wrote:
| Quote: | 1. You run the finalizers in a separate thread while the
program threads are still running.
|
Finalizers will normally be invoked throughout the lifetime
of the program as objects become collectable, so this will
happen routinely.
| Quote: | Since the finalizer holds a copy of the resource, you run into the obvious
problem of releasing the resource while the live object is still using it.
For a resource that is as thread safe as an int, this invokes undefined
behavior.
|
What live object? Finalizers are only invoked for objects
which have become inaccessible. There can be a problem only
if copies of the resource exist outside its holder and
finalizer. *Don't Do That(TM)*
| Quote: | 2. You terminate all threads and then run the finalizers.
|
And this is fine also, for a proper definition of "terminate".
| Quote: | This leaves the program (including the resources) in an inconsistent state,
which means that it isn't possible to release the resources safely.
|
Then that's not a proper definition of terminate.
| Quote: | Singletons do have a similar problem if you attempt to destroy them while
the program is alive, which is why we don't.
|
What do you mean "we"? Certainly _Modern C++ Design_ talks about
destroying singletons. And destructors of static objects are
supposed to run at program exit.
| Quote: | The only safe way (that I see) to run finalizers on exit is to cancel all
threads, drop all references to all objects, then force a garbage collection
just before exit.
|
Yes, I've said exactly the same thing. I am not choosing in this
thread to discuss how threads should be cancelled so as to still
leave the program in a consistent state, but I don't have to.
Since this must work in order for atexit and static destructors
to function properly, finalization will simply piggyback upon
whatever the solution is.
In this final phase, we drop all references except from the finalizers
themselves; that allows finalizers to control their order if there are
inter-resource dependencies.
| Quote: | Impossible in general if there is more than one programmer or the program
uses third-party libraries.
|
Nope. There's no harm in doing it, aside from some potential slowness,
so any subsystem that needs it just requests it.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Powered by phpBB © 2001, 2006 phpBB Group
|