[Gc] Feature suggestion: gc_cleanup call finalize() first
Neil Toronto
ntoronto at cs.byu.edu
Tue Apr 19 00:07:29 PDT 2005
New here, etc. Hello everyone, etc. :)
Great work Hans! I've started using the GC for C++, and I'm looking
forward to having real reference semantics. As much as I love the STL
and generic programming, it's just not what I want sometimes. This stuff
is wonderful with a compliant C++ compiler.
Anyway, I had a suggestion for finalization. Here's an example of
finalization usage, coded naively:
class istream : public gc_cleanup
{
public:
virtual bool is_closed() = 0;
virtual void close() = 0;
virtual ~istream()
{
if (!is_closed())
{
close();
alert_naughty_user_somehow();
}
}
};
class file_istream : public istream
{
public:
virtual void close()
{
printf("Closing open file\n");
}
};
The intent of the author is to have the abstract base class call its
descendant's close() when that descendant gets destroyed. It's not going
to work, though, because the compiler (a good one, anyway) will complain
that istream's destructor calls a virtual method. (A not-so-good
compiler would build something that throws a fit at run time.) Even if
is_closed() and close() were defined in istream it wouldn't work,
because inside istream's destructor, file_istream doesn't exist anymore.
(Semantically, anyway. The actual mechanics are an implementation
detail.) The methods in istream would get called.
If gc_cleanup's static cleanup() method called a virtual method
finalize() instead of (or as well as) the destructor, it could be made
to work easily:
class istream : public gc_cleanup
{
public:
virtual bool is_closed() = 0;
virtual void close() = 0;
virtual void finalize()
{
if (!is_closed())
{
close();
alert_naughty_user_somehow();
}
}
};
This works fine - I've tested it with a modified gc_cpp.h. (I added
about three lines of code.)
There's also a good meta-reason to do it this way, and it's one reason
it's done this way in Java and C#. Destructors chain because it's a
safe, structured way to deallocate memory. With GC, that's not
necessary, and calling a virtual finalize() makes more sense. If the
user wants chaining (which will be almost never), he can call the base
class finalize() manually.
Simple idea, easy implementation. What's not to love?
Neil
More information about the Gc
mailing list