[ZOOM] Object Owenership (Was: Value Returned from Set Option (Was: Catching up))

Adam Dickmeiss adam at indexdata.dk
Fri Nov 16 23:54:38 CET 2001


On Fri, Nov 16, 2001 at 11:35:07AM +0000, Ashley Sanders wrote:
> Adam wrote:
> 
> > I think Ashley wanted the reference to internal stuff in the
> > result set. And I can cope with that. The bright side is that
> > then I don't forget to destroy record objects returned
> > from _resultset_record(s). 
> 
> Well, as I just emailed to Mike, I prefer a pointer to an record
> owned by the resultSet. I didn't suggest a reference, but would
> have gone along with a reference if I could have figured a sensible
> way of implementing resultSet such that getRecord returns a reference.
> Maybe I'm just being blind and/or thick with this, but I can't
> come up with, to my mind, a sensible implementation of resultSet
> such that getRecord can return a reference to a record.
> Please enlighten me if I am being blind/stupid here.

There are two issues here. First thing is that you'd like
records returned being owned by the result set. Whether
it's a pointer, reference, whatever is not essential
with respect to the C binding. The important part is
that both C and C++ should do the same thing here.
The reason for me to be picky about this is that if a user of
the C API doesn't get this right , then either 

1) a memory leak is introduced or

2) a memory violation occurs at some point. 

Case 1) happens when the API returns a persistent record (not owned
by a result) and the API user doesn't destroy it. Case 2) happens
when the API user destroys an object that is owned by the result set.
These errors aren't catched by a compiler for the C binding.

Assuming we want records to be owned by the result set then we
must be careful with case 2). If we return record objects (well
they are interfaces, really), then you must handle 'delete r' on
the record pointer returned.. If you implement it using references
instead, then 'delete r' doesn't make sense. I don't have any strong
preferences for either solution. If you're having trouble with
a reference version of it here's some code that may help you.

// First, I added method getRecordR for the resultSet class:
    const record &getRecordR (size_t num) const;

// Then, made a class that's based on the abstract record class. 
class derivedRecord : public record {
  public:
    derivedRecord();
    ~derivedRecord();
    record *clone () const;
    recordSyntax recsyn () const;
    size_t nfields () const;
    char *field (const char *spec) const;
    const char *render () const;
    data *rawdata () const;
};

const record &resultSet::getRecordR (size_t pos) const
{
    derivedRecord *r = 0;  // get if from a cache, whatever..

    return *r; 
}

// Using it.
const record &give_me_targetinfo2 (connection *c)
{
    prefixQuery q("@attr exp1 1=1 targetinfo");
    resultSet *s = c->search(&q);
    const record &r = s->getRecordR(0);
    return r; 
}

// Adam

> Regards,
> 
> Ashley.
> 
> -- 
> Ashley Sanders                                a.sanders at mcc.ac.uk
> COPAC: A public bibliographic database from MIMAS, funded by JISC
>              http://copac.ac.uk/ - copac at mimas.ac.uk



More information about the ZOOM mailing list