Subject Re: [IB-Architect] New API: Object Life Time
Author Glebas Paulevicius
Jim,

>A high level exception handler may want to wipe out all references
>from a subsystem without elaborate cleanup code. There are better
>ways to do this, but involves building a set of wrappers for the
>API classes just to track use counts. I think it makes sense to
>give folks a break by making it accessible (though reasonable people
>may differ).

C++ exception specification says that once exception is thrown,
destructors are called for each fully constructed objects.
This feature is called "stack unwinding" or smth like that.
So - if you decrease reference in destructor - be sure -
language will do it for you. Unless MSVC thinks different :)

>>Jim, I have something deep inside me against having
>>Connection object in "unconnected" mode!
>
>Point well taken. Realistically, however, eliminating the
>unconnected state would virtually dictate a data source
>driver class to create connections and databases. Ultimately,
>however, the driver class would be doing exactly the same
>thing we're doing now but hiding the details.

Too high-tech for me. What is wrong with the following:

try
{
Driver driver;
Connection connection = driver.connect( "url:/blah/blah/blah", info );
}
catch( SQLException &exception )
{
printf( "Failed to connect" );
}

>Here is the JDBC driver class. Do you think we should add it?

Why not? Since it is JDBC... :)

class Driver
{
Connection connect( const char *url, Properties &info ) throw(
SQLException );
bool acceptsURL( const char *url ) throw( SQLException );
DriverPropertyInfo getPropertyInfo( const char *url, Properties &info )
throw( SQLException );
int getMajorVersion();
int getMinorVersion();
bool jdbcCompliant();
};

class ConnectionInst // to be derived from
{
int _refCount;
public:
ConnectionInst(): _refCount( 0 ) {}
virtual ~ConnectionInst() {}
void incRef() { _refCount++; }
bool decRef() { return --_refCount; }
};

class Connection
{
ConnectionInst *_inst;
public:
Connection( ConnectionInst *inst ): _inst( inst ) { _inst->incRef(); }
Connection( const ConnectionInst &that ): _inst( that._inst ) {
_inst->incRef(); }
~Connection() { if( _inst->decRef() ) delete _inst; }
};

>The above requires that the compiler have access to the implementation
>of all the classes in the object model, which isn't possible. The
>only way to use an instantiation of an abstract class is through a
>pointer.
>
>I think what you are suggesting is a wrapper around the wrapper. I
>certainly don't have any objection to somebody doing this, but I don't
>think it an essential part of the object model.

What I am suggesting is not "wrapper around wrapper" but
rather "how wrapper is organized internally".
Essentially, the great job Java does for you is allowing you
to treat ConnectionInst and Connection as one thing - "Connection"
plus manage refCount logic for you.

The cycle can be coded with language which has "if" and "goto".
However, C has "for" and "while" for it.

One can write object oriented code in C
always passing "this" as first parameter.
However, C++ has classes for it.

One can use Object and ObjectInst pairs as above and
mimic Java-style object management.
However, Java has it natively.

Don't be afraid of ConnectionInst. You can even get it out of the header.
Application programmer will only see Connection. No pointers/delete headache.
All done in destructors. Nice. Elegant. Java style.

Regards,
Glebas