]> granicus.if.org Git - postgis/commitdiff
Simplify support for PgSQL11 and other versions w/ memorycontext deleteion callbacks...
authorPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 20 Dec 2017 19:28:16 +0000 (19:28 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 20 Dec 2017 19:28:16 +0000 (19:28 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@16172 b70326c6-7e19-0410-871a-916f4a2858ee

extensions/address_standardizer/std_pg_hash.c
libpgcommon/lwgeom_transform.c
postgis/lwgeom_geos_prepared.c

index 68377141c6dffb6d47db72f07bbbfabf8155dde9..ffd55d2f38c745f8c9db8378a62b925a1667ef2c 100644 (file)
@@ -91,21 +91,6 @@ static void AddStdHashEntry(MemoryContext mcxt, STANDARDIZER *std);
 static StdHashEntry *GetStdHashEntry(MemoryContext mcxt);
 static void DeleteStdHashEntry(MemoryContext mcxt);
 
-/* Memory context cache function prototypes */
-static void StdCacheInit(MemoryContext context);
-static void StdCacheReset(MemoryContext context);
-static void StdCacheDelete(MemoryContext context);
-static bool StdCacheIsEmpty(MemoryContext context);
-
-#if POSTGIS_PGSQL_VERSION >= 96
-static void StdCacheStats(MemoryContext context, int level, bool print, MemoryContextCounters *totals);
-#else
-static void StdCacheStats(MemoryContext context, int level);
-#endif
-
-#ifdef MEMORY_CONTEXT_CHECKING
-static void StdCacheCheck(MemoryContext context);
-#endif
 
 static bool IsInStdPortalCache(StdPortalCache *STDCache,  char *lextab, char *gaztab, char *rultab);
 static STANDARDIZER *GetStdFromPortalCache(StdPortalCache *STDCache,  char *lextab, char *gaztab, char *rultab);
@@ -124,41 +109,19 @@ static int fetch_rules_columns(SPITupleTable *tuptable, rules_columns_t *rules_c
 static int load_rules(RULES *rules, char *tabname);
 
 
-/* Memory context definition must match the current version of PostgreSQL */
-static MemoryContextMethods StdCacheContextMethods =
-{
-    NULL,
-    NULL,
-    NULL,
-    StdCacheInit,
-    StdCacheReset,
-    StdCacheDelete,
-    NULL,
-    StdCacheIsEmpty,
-    StdCacheStats
-#ifdef MEMORY_CONTEXT_CHECKING
-    , StdCacheCheck
-#endif
-};
 
 
-static void
-StdCacheInit(MemoryContext context)
-{
-    /* NOP - initialized when first used. */
-}
-
 
 static void
-StdCacheReset(MemoryContext context)
-{
-    // NOP - Seems to be a required function
-}
+#if POSTGIS_PGSQL_VERSION < 95
 
-
-static void
 StdCacheDelete(MemoryContext context)
 {
+#else
+StdCacheDelete(void *ptr)
+{
+       MemoryContext context = (MemoryContext)ptr;
+#endif
     StdHashEntry *she;
 
     DBG("Enter: StdCacheDelete");
@@ -177,31 +140,34 @@ StdCacheDelete(MemoryContext context)
     DeleteStdHashEntry(context);
 }
 
+#if POSTGIS_PGSQL_VERSION < 95
 
-static bool
-StdCacheIsEmpty(MemoryContext context)
+static void
+StdCacheInit(MemoryContext context)
 {
-    // always return false - another required function
-    return FALSE;
+    /* NOP - initialized when first used. */
 }
 
 
-#if POSTGIS_PGSQL_VERSION >= 96
 static void
-StdCacheStats(MemoryContext context, int level, bool print, MemoryContextCounters *totals)
+StdCacheReset(MemoryContext context)
 {
-    // another required function
-    fprintf(stderr, "%s: STANDARDIZER context\n", context->name);
+    // NOP - Seems to be a required function
 }
-#else
+
+static bool
+StdCacheIsEmpty(MemoryContext context)
+{
+    // always return false - another required function
+    return FALSE;
+}
+
 static void
 StdCacheStats(MemoryContext context, int level)
 {
     // another required function
     fprintf(stderr, "%s: STANDARDIZER context\n", context->name);
 }
-#endif
-
 
 #ifdef MEMORY_CONTEXT_CHECKING
 static void
@@ -211,6 +177,25 @@ StdCacheCheck(MemoryContext context)
 }
 #endif
 
+/* Memory context definition must match the current version of PostgreSQL */
+static MemoryContextMethods StdCacheContextMethods =
+{
+    NULL,
+    NULL,
+    NULL,
+    StdCacheInit,
+    StdCacheReset,
+    StdCacheDelete,
+    NULL,
+    StdCacheIsEmpty,
+    StdCacheStats
+#ifdef MEMORY_CONTEXT_CHECKING
+    , StdCacheCheck
+#endif
+};
+
+#endif /* POSTGIS_PGSQL_VERSION < 95 */
+
 
 uint32
 mcxt_ptr_hash_std(const void *key, Size keysize)
@@ -397,10 +382,27 @@ AddToStdPortalCache(StdPortalCache *STDCache, char *lextab, char *gaztab, char *
 
     DBG("Adding item to STD cache ('%s', '%s', '%s') index %d", lextab, gaztab, rultab, STDCache->NextSlot);
 
+
+#if POSTGIS_PGSQL_VERSION < 95
     STDMemoryContext = MemoryContextCreate(T_AllocSetContext, 8192,
                                            &StdCacheContextMethods,
                                            STDCache->StdCacheContext,
                                            "PAGC STD Memory Context");
+#else
+       STDMemoryContext =  AllocSetContextCreate(STDCache->StdCacheContext,
+                                                 "PAGC STD Memory Context",
+                                                 ALLOCSET_SMALL_SIZES);
+
+       /* PgSQL comments suggest allocating callback in the context */
+       /* being managed, so that the callback object gets cleaned along with */
+       /* the context */
+       MemoryContextCallback *callback = MemoryContextAlloc(STDMemoryContext, sizeof(MemoryContextCallback));
+       callback->arg = (void*)(STDMemoryContext);
+       callback->func = StdCacheDelete;
+       MemoryContextRegisterResetCallback(STDMemoryContext, callback);
+#endif
+
+
 
     /* Create the backend hash if it doesn't already exist */
     DBG("Check if StdHash exists (%p)", StdHash);
index 57f8604099ac1c0a0641ceb24b974d472cf8a21b..1993326f0348bc02ee327de6fe67f9aa0fa86eaf 100644 (file)
@@ -64,9 +64,6 @@ typedef struct struct_PJHashEntry
 {
        MemoryContext ProjectionContext;
        projPJ projection;
-#if POSTGIS_PGSQL_VERSION >= 96
-       MemoryContextCallback callback; /* for releasing hashentry when done */
-#endif
 }
 PJHashEntry;
 
@@ -76,10 +73,7 @@ uint32 mcxt_ptr_hash(const void *key, Size keysize);
 
 static HTAB *CreatePJHash(void);
 static void AddPJHashEntry(MemoryContext mcxt, projPJ projection);
-#if POSTGIS_PGSQL_VERSION < 96
-/** see note on function def why this is useless **/
 static projPJ GetPJHashEntry(MemoryContext mcxt);
-#endif
 static void DeletePJHashEntry(MemoryContext mcxt);
 
 /* Internal Cache API */
@@ -93,39 +87,33 @@ static void DeleteFromPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid);
 static bool IsPROJ4LibPathSet = false;
 void SetPROJ4LibPath(void);
 
-#if POSTGIS_PGSQL_VERSION < 96
-static void PROJ4SRSCacheDelete(MemoryContext context);
+
+static void
+#if POSTGIS_PGSQL_VERSION < 95
+PROJ4SRSCacheDelete(MemoryContext context)
+{
 #else
-static void PROJ4SRSCacheDelete(void *arg);
+PROJ4SRSCacheDelete(void *ptr)
+{
+       MemoryContext context = (MemoryContext)ptr;
 #endif
-/* Memory context cache function prototypes
-Only need for PostgreSQL where we will not be using a built-in memory context*/
-#if POSTGIS_PGSQL_VERSION < 96
-static void PROJ4SRSCacheInit(MemoryContext context);
-static void PROJ4SRSCacheReset(MemoryContext context);
-static bool PROJ4SRSCacheIsEmpty(MemoryContext context);
+       projPJ projection;
 
-static void PROJ4SRSCacheStats(MemoryContext context, int level);
+       /* Lookup the projPJ pointer in the global hash table so we can free it */
+       projection = GetPJHashEntry(context);
 
-#ifdef MEMORY_CONTEXT_CHECKING
-static void PROJ4SRSCacheCheck(MemoryContext context);
-#endif
+       if (!projection)
+               elog(ERROR, "PROJ4SRSCacheDelete: Trying to delete non-existant projection object with MemoryContext key (%p)", (void *)context);
 
-static MemoryContextMethods PROJ4SRSCacheContextMethods =
-{
-       NULL,
-       NULL,
-       NULL,
-       PROJ4SRSCacheInit,
-       PROJ4SRSCacheReset,
-       PROJ4SRSCacheDelete,
-       NULL,
-       PROJ4SRSCacheIsEmpty,
-       PROJ4SRSCacheStats
-#ifdef MEMORY_CONTEXT_CHECKING
-       ,PROJ4SRSCacheCheck
-#endif
-};
+       POSTGIS_DEBUGF(3, "deleting projection object (%p) with MemoryContext key (%p)", projection, context);
+       /* Free it */
+       pj_free(projection);
+
+       /* Remove the hash entry as it is no longer needed */
+       DeletePJHashEntry(context);
+}
+
+#if POSTGIS_PGSQL_VERSION < 95
 
 static void
 PROJ4SRSCacheInit(MemoryContext context)
@@ -156,11 +144,7 @@ PROJ4SRSCacheIsEmpty(MemoryContext context)
 }
 
 static void
-#if POSTGIS_PGSQL_VERSION >= 96
-PROJ4SRSCacheStats(MemoryContext context, int level, bool print, MemoryContextCounters *totals)
-#else
 PROJ4SRSCacheStats(MemoryContext context, int level)
-#endif
 {
        /*
         * Simple stats display function - we must supply a function since this call is mandatory according to tgl
@@ -181,36 +165,24 @@ PROJ4SRSCacheCheck(MemoryContext context)
 }
 #endif
 
-#endif
-
-
-static void
-#if POSTGIS_PGSQL_VERSION < 96
-PROJ4SRSCacheDelete(MemoryContext context)
-{
-       projPJ projection;
-       /* Lookup the projPJ pointer in the global hash table so we can free it */
-       projection = GetPJHashEntry(context);
-#else  /** to use built-in memory context we need to provide our delete hook in a form suitable for callback **/
-PROJ4SRSCacheDelete(void *arg)
+/* Memory context definition must match the current version of PostgreSQL */
+static MemoryContextMethods PROJ4SRSCacheContextMethods =
 {
-       PJHashEntry *he = (PJHashEntry *) arg;
-       projPJ projection = he->projection;
-       MemoryContext context;
-       context = he->ProjectionContext;
+       NULL,
+       NULL,
+       NULL,
+       PROJ4SRSCacheInit,
+       PROJ4SRSCacheReset,
+       PROJ4SRSCacheDelete,
+       NULL,
+       PROJ4SRSCacheIsEmpty,
+       PROJ4SRSCacheStats
+#ifdef MEMORY_CONTEXT_CHECKING
+       ,PROJ4SRSCacheCheck
 #endif
-       if (!projection)
-               elog(ERROR, "PROJ4SRSCacheDelete: Trying to delete non-existant projection object with MemoryContext key (%p)", (void *)context);
-
-       POSTGIS_DEBUGF(3, "deleting projection object (%p) with MemoryContext key (%p)", projection, context);
-
-       /* Free it */
-       pj_free(projection);
-
-       /* Remove the hash entry as it is no longer needed */
-       DeletePJHashEntry(context);
-}
+};
 
+#endif /* POSTGIS_PGSQL_VERSION < 95 */
 
 /*
  * PROJ4 projPJ Hash Table functions
@@ -266,11 +238,6 @@ static void AddPJHashEntry(MemoryContext mcxt, projPJ projection)
        }
 }
 
-/** TODO: May reconsider changing this to return entry as name implies
- *  For now it's useless when we are using built-in context cause
- * we need the entry for cleanup
- * */
-#if POSTGIS_PGSQL_VERSION < 96
 static projPJ GetPJHashEntry(MemoryContext mcxt)
 {
        void **key;
@@ -284,7 +251,7 @@ static projPJ GetPJHashEntry(MemoryContext mcxt)
 
        return he->projection;
 }
-#endif
+
 
 static void DeletePJHashEntry(MemoryContext mcxt)
 {
@@ -566,22 +533,27 @@ AddToPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid, int other_srid)
         * store it in the backend hash
         */
        POSTGIS_DEBUGF(3, "adding SRID %d with proj4text \"%s\" to query cache at index %d", srid, proj_str, PROJ4Cache->PROJ4SRSCacheCount);
-#if POSTGIS_PGSQL_VERSION < 96
+
+#if POSTGIS_PGSQL_VERSION < 95
        PJMemoryContext = MemoryContextCreate(T_AllocSetContext, 8192,
-                                                                                       &PROJ4SRSCacheContextMethods,
-                                                                                       PROJ4Cache->PROJ4SRSCacheContext,
-                                                                                       "PostGIS PROJ4 PJ Memory Context");
+                                             &PROJ4SRSCacheContextMethods,
+                                             PROJ4Cache->PROJ4SRSCacheContext,
+                                             "PostGIS PROJ4 PJ Memory Context");
 #else
-/** TODO: Verify that CacheMemoryContext is best.  I originally tried PortalMemoryContext
- * as suggested on pg-hackers, but that caused failures in delete of hash entries,
- * I presume because PortalMemory was sometimes cleaned before delete happened.  **/
-       PJMemoryContext = AllocSetContextCreate(CacheMemoryContext,
-                                                                                        "PostGIS PROJ4 PJ Memory Context",
-                                                                                        ALLOCSET_SMALL_SIZES);
-
+       PJMemoryContext = AllocSetContextCreate(PROJ4Cache->PROJ4SRSCacheContext,
+                                               "PostGIS PROJ4 PJ Memory Context",
+                                               ALLOCSET_SMALL_SIZES);
+
+       /* PgSQL comments suggest allocating callback in the context */
+       /* being managed, so that the callback object gets cleaned along with */
+       /* the context */
+       MemoryContextCallback *callback = MemoryContextAlloc(PJMemoryContext, sizeof(MemoryContextCallback));
+       callback->arg = (void*)PJMemoryContext;
+       callback->func = PROJ4SRSCacheDelete;
+       MemoryContextRegisterResetCallback(PJMemoryContext, callback);
 #endif
 
-       /* Create the backend hash if it doesn't already exist */
+       /* Create the backend hash if it doesn't already exist */
        if (!PJHash)
                PJHash = CreatePJHash();
 
@@ -593,25 +565,6 @@ AddToPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid, int other_srid)
 
        AddPJHashEntry(PJMemoryContext, projection);
 
-       /* Register cleanup callback only for PostgreSQL where
-        * we are using built-in context instead of our own
-        */
-       #if POSTGIS_PGSQL_VERSION >= 96
-       /* The hash key is the MemoryContext pointer */
-       void **key;
-       key = (void *)&PJMemoryContext;
-       /** We need to do this because GetPJHashEntry returns the projection
-        * and NOT the entry as the name would lead you to believe **/
-       PJHashEntry *he;
-
-       /* Return the projection object from the hash */
-       he = (PJHashEntry *) hash_search(PJHash, key, HASH_FIND, NULL);
-       he->callback.func = PROJ4SRSCacheDelete;
-       he->callback.arg = (void *) he;
-       MemoryContextRegisterResetCallback(he->ProjectionContext,
-                                                                               &he->callback);
-       #endif
-
        PROJ4Cache->PROJ4SRSCache[PROJ4Cache->PROJ4SRSCacheCount].srid = srid;
        PROJ4Cache->PROJ4SRSCache[PROJ4Cache->PROJ4SRSCacheCount].projection = projection;
        PROJ4Cache->PROJ4SRSCache[PROJ4Cache->PROJ4SRSCacheCount].projection_mcxt = PJMemoryContext;
@@ -700,51 +653,6 @@ Proj4Cache GetPROJ4Cache(FunctionCallInfo fcinfo) {
        return (Proj4Cache)GetPROJ4SRSCache(fcinfo);
 }
 
-#if 0
-static PROJ4PortalCache *GetPROJ4SRSCache(FunctionCallInfo fcinfo)
-{
-       PROJ4PortalCache *PROJ4Cache = (GetGeomCache(fcinfo))->proj;
-
-       /*
-        * If we have not already created PROJ4 cache for this portal
-        * then create it
-        */
-       if (fcinfo->flinfo->fn_extra == NULL)
-       {
-               MemoryContext old_context;
-
-               old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
-               PROJ4Cache = palloc(sizeof(PROJ4PortalCache));
-               MemoryContextSwitchTo(old_context);
-
-               if (PROJ4Cache)
-               {
-                       int i;
-
-                       POSTGIS_DEBUGF(3, "Allocating PROJ4Cache for portal with transform() MemoryContext %p", fcinfo->flinfo->fn_mcxt);
-                       /* Put in any required defaults */
-                       for (i = 0; i < PROJ4_CACHE_ITEMS; i++)
-                       {
-                               PROJ4Cache->PROJ4SRSCache[i].srid = SRID_UNKNOWN;
-                               PROJ4Cache->PROJ4SRSCache[i].projection = NULL;
-                               PROJ4Cache->PROJ4SRSCache[i].projection_mcxt = NULL;
-                       }
-                       PROJ4Cache->PROJ4SRSCacheCount = 0;
-                       PROJ4Cache->PROJ4SRSCacheContext = fcinfo->flinfo->fn_mcxt;
-
-                       /* Store the pointer in fcinfo->flinfo->fn_extra */
-                       fcinfo->flinfo->fn_extra = PROJ4Cache;
-               }
-       }
-       else
-       {
-               /* Use the existing cache */
-               PROJ4Cache = fcinfo->flinfo->fn_extra;
-       }
-
-       return PROJ4Cache ;
-}
-#endif
 
 int
 GetProjectionsUsingFCInfo(FunctionCallInfo fcinfo, int srid1, int srid2, projPJ *pj1, projPJ *pj2)
index a5f260e191a5ca6e720115229fb156008224d71d..50e85636b1ea03818ea8e7e291ffbd7c61c3c1af 100644 (file)
@@ -79,14 +79,11 @@ static HTAB* PrepGeomHash = NULL;
 
 #define PREPARED_BACKEND_HASH_SIZE     32
 
-typedef struct PrepGeomHashEntry
+typedef struct
 {
        MemoryContext context;
        const GEOSPreparedGeometry* prepared_geom;
        const GEOSGeometry* geom;
-#if POSTGIS_PGSQL_VERSION >= 96
-       MemoryContextCallback callback; /* for releasing hashentry when done */
-#endif
 }
 PrepGeomHashEntry;
 
@@ -97,41 +94,38 @@ static void AddPrepGeomHashEntry(PrepGeomHashEntry pghe);
 static PrepGeomHashEntry *GetPrepGeomHashEntry(MemoryContext mcxt);
 static void DeletePrepGeomHashEntry(MemoryContext mcxt);
 
-#if POSTGIS_PGSQL_VERSION < 96
-static void PreparedCacheDelete(MemoryContext context);
+
+static void
+#if POSTGIS_PGSQL_VERSION < 95
+PreparedCacheDelete(MemoryContext context)
+{
 #else
-static void  PreparedCacheDelete(void *arg);
+PreparedCacheDelete(void *ptr)
+{
+       MemoryContext context = (MemoryContext)ptr;
 #endif
-/* Memory context cache function prototypes
-Only need for PostgreSQL where we will not be using a built-in memory context*/
-#if POSTGIS_PGSQL_VERSION < 96
-static void PreparedCacheInit(MemoryContext context);
-static void PreparedCacheReset(MemoryContext context);
 
-static bool PreparedCacheIsEmpty(MemoryContext context);
+       PrepGeomHashEntry* pghe;
 
-static void PreparedCacheStats(MemoryContext context, int level);
+       /* Lookup the hash entry pointer in the global hash table so we can free it */
+       pghe = GetPrepGeomHashEntry(context);
 
-#ifdef MEMORY_CONTEXT_CHECKING
-static void PreparedCacheCheck(MemoryContext context);
-#endif
+       if (!pghe)
+               elog(ERROR, "PreparedCacheDelete: Trying to delete non-existant hash entry object with MemoryContext key (%p)", (void *)context);
 
-static MemoryContextMethods PreparedCacheContextMethods =
-{
-       NULL,
-       NULL,
-       NULL,
-       PreparedCacheInit,
-       PreparedCacheReset,
-       PreparedCacheDelete,
-       NULL,
-       PreparedCacheIsEmpty,
-       PreparedCacheStats
-#ifdef MEMORY_CONTEXT_CHECKING
-       , PreparedCacheCheck
-#endif
-};
+       POSTGIS_DEBUGF(3, "deleting geom object (%p) and prepared geom object (%p) with MemoryContext key (%p)", pghe->geom, pghe->prepared_geom, context);
 
+       /* Free them */
+       if ( pghe->prepared_geom )
+               GEOSPreparedGeom_destroy( pghe->prepared_geom );
+       if ( pghe->geom )
+               GEOSGeom_destroy( (GEOSGeometry *)pghe->geom );
+
+       /* Remove the hash entry as it is no longer needed */
+       DeletePrepGeomHashEntry(context);
+}
+
+#if POSTGIS_PGSQL_VERSION < 95
 static void
 PreparedCacheInit(MemoryContext context)
 {
@@ -141,7 +135,6 @@ PreparedCacheInit(MemoryContext context)
         */
 }
 
-
 static void
 PreparedCacheReset(MemoryContext context)
 {
@@ -169,7 +162,6 @@ PreparedCacheStats(MemoryContext context, int level)
         * (see postgis-devel archives July 2007)
           fprintf(stderr, "%s: Prepared context\n", context->name);
         */
-
 }
 
 #ifdef MEMORY_CONTEXT_CHECKING
@@ -182,39 +174,26 @@ PreparedCacheCheck(MemoryContext context)
         */
 }
 #endif
-#endif
 
-
-
-static void
-#if POSTGIS_PGSQL_VERSION < 96
-PreparedCacheDelete(MemoryContext context)
-{
-       PrepGeomHashEntry* pghe;
-       /* Lookup the hash entry pointer in the global hash table so we can free it */
-       pghe = GetPrepGeomHashEntry(context);
-#else  /** to use built-in memory context we need to provide our delete hook in a form suitable for callback **/
-PreparedCacheDelete(void *arg)
+/* Memory context definition must match the current version of PostgreSQL */
+static MemoryContextMethods PreparedCacheContextMethods =
 {
-       PrepGeomHashEntry *pghe =  (PrepGeomHashEntry *) arg;
-       MemoryContext context;
-       if (pghe)
-               context = pghe->context;
+       NULL,
+       NULL,
+       NULL,
+       PreparedCacheInit,
+       PreparedCacheReset,
+       PreparedCacheDelete,
+       NULL,
+       PreparedCacheIsEmpty,
+       PreparedCacheStats
+#ifdef MEMORY_CONTEXT_CHECKING
+       , PreparedCacheCheck
 #endif
-       if (!pghe)
-               elog(ERROR, "PreparedCacheDelete: Trying to delete non-existant hash entry object with MemoryContext key (%p)", (void *)context);
+};
 
-       POSTGIS_DEBUGF(3, "deleting geom object (%p) and prepared geom object (%p) with MemoryContext key (%p)", pghe->geom, pghe->prepared_geom, context);
+#endif /* POSTGIS_PGSQL_VERSION < 95 */
 
-       /* Free them */
-       if ( pghe->prepared_geom )
-               GEOSPreparedGeom_destroy( pghe->prepared_geom );
-       if ( pghe->geom )
-               GEOSGeom_destroy( (GEOSGeometry *)pghe->geom );
-
-       /* Remove the hash entry as it is no longer needed */
-       DeletePrepGeomHashEntry(context);
-}
 
 
 /* TODO: put this in common are for both transform and prepared
@@ -321,6 +300,7 @@ PrepGeomCacheBuilder(const LWGEOM *lwgeom, GeomCache *cache)
 {
        PrepGeomCache* prepcache = (PrepGeomCache*)cache;
        PrepGeomHashEntry* pghe;
+
        /*
        * First time through? allocate the global hash.
        */
@@ -332,26 +312,27 @@ PrepGeomCacheBuilder(const LWGEOM *lwgeom, GeomCache *cache)
        */
        if ( ! prepcache->context_callback )
        {
-               /** TODO: This is yucky that we are reusing the same variable name
-                * we used as a global pointer above, as a local variable.  We should reconsider this.
-                * Took me a while to realize they weren't the same. **/
                PrepGeomHashEntry pghe;
-               #if POSTGIS_PGSQL_VERSION < 96
-                       prepcache->context_callback = MemoryContextCreate(T_AllocSetContext, 8192,
-                                                                                       &PreparedCacheContextMethods,
-                                                                                       prepcache->context_statement,
-                                                                                       "PostGIS Prepared Geometry Context");
-               #else
-/**For 9.5+ we can use a PostgreSQL context instead of creating our own and add a delete callback to it.
- * TODO: change so not just PostgreSQL 11 goes thru this loop **/
-/** TODO: Verify that CacheMemoryContext is best.  I originally tried PortalMemoryContext
- * as suggested on pg-hackers, but that caused failures in delete of hash entries,
- * I presume because PortalMemory was sometimes cleaned before delete happened.  **/
-                       prepcache->context_callback = AllocSetContextCreate(CacheMemoryContext,
-                                                                                        "PostGIS PROJ4 PJ Memory Context",
-                                                                                       ALLOCSET_SMALL_SIZES
-                       );
-               #endif
+#if POSTGIS_PGSQL_VERSION < 95
+               prepcache->context_callback = MemoryContextCreate(T_AllocSetContext, 8192,
+                                            &PreparedCacheContextMethods,
+                                            prepcache->context_statement,
+                                            "PostGIS Prepared Geometry Context");
+
+#else
+               prepcache->context_callback = AllocSetContextCreate(prepcache->context_statement,
+                                          "PostGIS Prepared Geometry Context",
+                                          ALLOCSET_SMALL_SIZES);
+
+               /* PgSQL comments suggest allocating callback in the context */
+               /* being managed, so that the callback object gets cleaned along with */
+               /* the context */
+               MemoryContextCallback *callback = MemoryContextAlloc(prepcache->context_callback, sizeof(MemoryContextCallback));
+               callback->arg = (void*)(prepcache->context_callback);
+               callback->func = PreparedCacheDelete;
+               MemoryContextRegisterResetCallback(prepcache->context_callback, callback);
+#endif
+
                pghe.context = prepcache->context_callback;
                pghe.geom = 0;
                pghe.prepared_geom = 0;
@@ -389,15 +370,6 @@ PrepGeomCacheBuilder(const LWGEOM *lwgeom, GeomCache *cache)
        * extra references in a global hash object.
        */
        pghe = GetPrepGeomHashEntry(prepcache->context_callback);
-
-       #if POSTGIS_PGSQL_VERSION >= 96
-       /* Immediately register cleanup callback only for PostgreSQL where
-        we are using built in context instead of our own  */
-       pghe->callback.func = PreparedCacheDelete;
-       pghe->callback.arg = (void *) pghe;
-       MemoryContextRegisterResetCallback(pghe->context,
-                                                                               &pghe->callback);
-       #endif
        if ( ! pghe )
        {
                lwpgerror("PrepGeomCacheBuilder failed to find hash entry for context %p", prepcache->context_callback);
@@ -407,8 +379,6 @@ PrepGeomCacheBuilder(const LWGEOM *lwgeom, GeomCache *cache)
        pghe->geom = prepcache->geom;
        pghe->prepared_geom = prepcache->prepared_geom;
 
-
-
        return LW_SUCCESS;
 }