[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