[gdal-dev] Re: [SoC] GDAL WKTRaster weekly report #9

Mateusz Loskot mateusz at loskot.net
Sun Aug 2 08:51:19 EDT 2009


Jorge Arévalo wrote:
> When I create an overview (a children dataset), its properties are
> the same properties of the general dataset (his parent), apart from
> pixel size, table name and column_name, of course. The problem
> appears when sharing the PGconn object.
> 
> My code looks like this:
> 
> poDS->overview[i]->hPGconn = poDS->hPGconn
> 
> If each dataset's destructor (from the general one and from the 
> overviews) calls PQfinish over the same object, I get a segmentation 
> fault after the first time, of course. So, I have 2 options: - Detect
> when a connection object has been freed, and perform only one call.
> How should I do this?

If I understand it correctly, the problem can be summarised in some
kind of pseudo-code as follows:

struct Overview
{
   PGconn* c;
   Overview(PGconn* c) : c(c) {}
   ~Overview() { PQfinish(c); }

};

struct Dataset
{
   PGconn* c;
   Dataset(char const* connstr) { /*connect to pgsql*/ }
   ~Dataset() {  PQfinish(c) ; c = 0; }
   Overview get_overview() { return Overview(c); }
};


{
   Overview ov;
   {
      Dataset d(...); // connect
      ov = d.get_overview(); // side-effect: share connection
   }  // Dataset dctor calls PQfinish

   // Problem #1: Overview's connection no longer valid
} // Problem #2: Overview dctor tries to close and fails

Note: Overview here may be a subdataset, no difference between the two
for the problem analysis.

Assuming this example reproduces the problem correctly, then
there is no way to detect in Overview's dctor that
connection is still valid.

After Dataset dctor is called, the c pointer in Overview is a dangling
pointer which stores an address in memory, but that address no longer
identifies PGconn object.

> - Don't share the PGconn object. Should I declare a static PGconn
> pointer?

It would work just in the opposite direction - such static pointer would
be shared. Concept of static object == concept of global object.
They are used to implement shared resource, though in a weak and
primitive way.

> What is the best approach?

First, you have to identify if lifetime of Dataset and Overview (or
Subdataset) is predictable - can Overview live longer than Dataset or
lifetime of Dataset always exceeds lifetime of Overview object.

1. The Dataset always life longer is the simplest case, simply close
connection only from Dataset and don't close it from Overview.
In other words, Overview's connection is a weak reference [1] to
connection in Dataset - meaning, Dataset is the only owner of connection.

[1] http://en.wikipedia.org/wiki/Weak_reference

2. However, if Overview object can live longer than Dataset
or moreover, you are not able to determine/predict what's
possible lifetime of Dataset and Overview, then IMHO the best
approach is to make PGconn a real shared object between Dataset
and Overview.

The simplest implementation is to use shared_ptr<T> from
std::tr1 (in GCC 4.3+ or Visual C++ 9.0+) or from Boost libraries.
However, I presume these are forbidden in GDAL, so you'd need to provide
some minimal implementation of reference counting pattern on your own.
Scott Meyers' example may be helpful:
http://www.aristeia.com/BookErrata/M29Source.html

Best regards,
-- 
Mateusz Loskot, http://mateusz.loskot.net
Charter Member of OSGeo, http://osgeo.org


More information about the gdal-dev mailing list