Changeset: bf2eda8dcd71 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/bf2eda8dcd71
Branch: Dec2023
Log Message:

Merge geos-reentrant branch into Dec2023: use reentrant interfaces of geos 
library.


diffs (truncated from 4088 to 300 lines):

diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -385,6 +385,7 @@ const char *MT_thread_getalgorithm(void)
 void *MT_thread_getdata(void);
 const char *MT_thread_getname(void);
 bool MT_thread_init(void);
+gdk_return MT_thread_init_add_callback(void (*init)(void *), void 
(*destroy)(void *), void *data);
 bool MT_thread_register(void);
 void MT_thread_set_qry_ctx(QryCtx *ctx);
 void MT_thread_setalgorithm(const char *algo);
diff --git a/gdk/gdk_system.c b/gdk/gdk_system.c
--- a/gdk/gdk_system.c
+++ b/gdk/gdk_system.c
@@ -184,10 +184,18 @@ GDKlockstatistics(int what)
 
 #endif /* LOCK_STATS */
 
+struct thread_funcs {
+       void (*init)(void *);
+       void (*destroy)(void *);
+       void *data;
+};
+
 static struct mtthread {
        struct mtthread *next;
        void (*func) (void *);  /* function to be called */
        void *data;             /* and its data */
+       struct thread_funcs *thread_funcs; /* callback funcs */
+       int nthread_funcs;
        MT_Lock *lockwait;      /* lock we're waiting for */
        MT_Sema *semawait;      /* semaphore we're waiting for */
        MT_Cond *condwait;      /* condition variable we're waiting for */
@@ -686,6 +694,36 @@ MT_thread_override_limits(void)
        return self && self->limit_override;
 }
 
+static struct thread_init_cb {
+       struct thread_init_cb *next;
+       void (*init)(void *);
+       void (*destroy)(void *);
+       void *data;
+} *init_cb;
+static MT_Lock thread_init_lock = MT_LOCK_INITIALIZER(thread_init_lock);
+
+gdk_return
+MT_thread_init_add_callback(void (*init)(void *), void (*destroy)(void *), 
void *data)
+{
+       struct thread_init_cb *p = GDKmalloc(sizeof(struct thread_init_cb));
+
+       if (p == NULL)
+               return GDK_FAIL;
+       *p = (struct thread_init_cb) {
+               .init = init,
+               .destroy = destroy,
+               .next = NULL,
+               .data = data,
+       };
+       MT_lock_set(&thread_init_lock);
+       struct thread_init_cb **pp = &init_cb;
+       while (*pp)
+               pp = &(*pp)->next;
+       *pp = p;
+       MT_lock_unset(&thread_init_lock);
+       return GDK_SUCCEED;
+}
+
 #ifdef HAVE_PTHREAD_H
 static void *
 #else
@@ -719,7 +757,16 @@ thread_starter(void *arg)
        self->data = NULL;
        self->sp = THRsp();
        thread_setself(self);
+       for (int i = 0; i < self->nthread_funcs; i++) {
+               if (self->thread_funcs[i].init)
+                       
(*self->thread_funcs[i].init)(self->thread_funcs[i].data);
+       }
        (*self->func)(data);
+       for (int i = 0; i < self->nthread_funcs; i++) {
+               if (self->thread_funcs[i].destroy)
+                       
(*self->thread_funcs[i].destroy)(self->thread_funcs[i].data);
+       }
+       free(self->thread_funcs);
        ATOMIC_SET(&self->exited, 1);
        TRC_DEBUG(THRD, "Exit thread \"%s\"\n", self->threadname);
        return 0;               /* NULL for pthreads, 0 for Windows */
@@ -843,6 +890,33 @@ MT_create_thread(MT_Id *t, void (*f) (vo
                .refs = 1,
                .tid = mtid,
        };
+       MT_lock_set(&thread_init_lock);
+       /* remember the list of callback functions we need to call for
+        * this thread (i.e. anything registered so far) */
+       for (struct thread_init_cb *p = init_cb; p; p = p->next)
+               self->nthread_funcs++;
+       if (self->nthread_funcs > 0) {
+               self->thread_funcs = malloc(self->nthread_funcs * 
sizeof(*self->thread_funcs));
+               if (self->thread_funcs == NULL) {
+                       GDKsyserror("Cannot allocate memory\n");
+                       MT_lock_unset(&thread_init_lock);
+                       free(self);
+#ifdef HAVE_PTHREAD_H
+                       pthread_attr_destroy(&attr);
+#endif
+                       return -1;
+               }
+               int n = 0;
+               for (struct thread_init_cb *p = init_cb; p; p = p->next) {
+                       self->thread_funcs[n++] = (struct thread_funcs) {
+                               .init = p->init,
+                               .destroy = p->destroy,
+                               .data = p->data,
+                       };
+               }
+       }
+       MT_lock_unset(&thread_init_lock);
+
        ATOMIC_INIT(&self->exited, 0);
        strcpy_len(self->threadname, threadname, sizeof(self->threadname));
        char *p;
@@ -869,6 +943,7 @@ MT_create_thread(MT_Id *t, void (*f) (vo
 #endif
        if (ret != 0) {
                GDKsyserr(ret, "Cannot start thread");
+               free(self->thread_funcs);
                free(self);
                return -1;
        }
@@ -877,6 +952,7 @@ MT_create_thread(MT_Id *t, void (*f) (vo
                              0, &self->wtid);
        if (self->hdl == NULL) {
                GDKwinerror("Failed to create thread");
+               free(self->thread_funcs);
                free(self);
                return -1;
        }
diff --git a/gdk/gdk_system.h b/gdk/gdk_system.h
--- a/gdk/gdk_system.h
+++ b/gdk/gdk_system.h
@@ -198,6 +198,7 @@ gdk_export bool MT_thread_init(void);
 gdk_export int MT_create_thread(MT_Id *t, void (*function) (void *),
                                void *arg, enum MT_thr_detach d,
                                const char *threadname);
+gdk_export gdk_return MT_thread_init_add_callback(void (*init)(void *), void 
(*destroy)(void *), void *data);
 gdk_export bool MT_thread_register(void);
 gdk_export void MT_thread_deregister(void);
 gdk_export const char *MT_thread_getname(void);
diff --git a/geom/lib/libgeom.c b/geom/lib/libgeom.c
--- a/geom/lib/libgeom.c
+++ b/geom/lib/libgeom.c
@@ -32,20 +32,43 @@ geomerror(_In_z_ _Printf_format_string_ 
        va_end(va);
 }
 
-void
+static MT_TLS_t geom_tls_key;
+
+static void
+libgeom_tls_init(void *dummy)
+{
+       (void)dummy;
+       GEOSContextHandle_t ctx = GEOS_init_r ();
+       GEOSContext_setNoticeHandler_r(ctx, (GEOSMessageHandler) geomerror);
+       GEOSContext_setErrorHandler_r(ctx, (GEOSMessageHandler) geomerror);
+       GEOS_setWKBByteOrder_r(ctx, 1); /* NDR (little endian) */
+       MT_tls_set(geom_tls_key, ctx);
+}
+
+static void
+libgeom_tls_exit(void *dummy)
+{
+       (void)dummy;
+       GEOSContextHandle_t ctx = MT_tls_get(geom_tls_key);
+       GEOS_finish_r(ctx);
+}
+
+GEOSContextHandle_t
+libgeom_tls(void)
+{
+       return MT_tls_get(geom_tls_key);
+}
+
+gdk_return
 libgeom_init(void)
 {
-       initGEOS((GEOSMessageHandler) geomerror, (GEOSMessageHandler) 
geomerror);
-    // TODO: deprecated call REMOVE    
-       GEOS_setWKBByteOrder(1);        /* NDR (little endian) */
+       if (MT_alloc_tls(&geom_tls_key) != GDK_SUCCEED ||
+               MT_thread_init_add_callback(libgeom_tls_init, libgeom_tls_exit, 
NULL) != GDK_SUCCEED)
+               return GDK_FAIL;
+
        printf("# MonetDB/GIS module loaded\n");
        fflush(stdout);         /* make merovingian see this *now* */
-}
-
-void
-libgeom_exit(void)
-{
-       finishGEOS();
+       return GDK_SUCCEED;
 }
 
 bool
@@ -64,10 +87,10 @@ wkb2geos(const wkb *geomWKB)
        if (is_wkb_nil(geomWKB))
                return NULL;
 
-       geosGeometry = GEOSGeomFromWKB_buf((unsigned char *) geomWKB->data, 
geomWKB->len);
+       geosGeometry = GEOSGeomFromWKB_buf_r(geoshandle, (unsigned char *) 
geomWKB->data, geomWKB->len);
 
        if (geosGeometry != NULL)
-               GEOSSetSRID(geosGeometry, geomWKB->srid);
+               GEOSSetSRID_r(geoshandle, geosGeometry, geomWKB->srid);
 
        return geosGeometry;
 }
diff --git a/geom/lib/libgeom.h b/geom/lib/libgeom.h
--- a/geom/lib/libgeom.h
+++ b/geom/lib/libgeom.h
@@ -30,11 +30,13 @@
 #define libgeom_export extern
 #endif
 
+#define GEOS_USE_ONLY_R_API 1
 #include <geos_c.h>
 #ifdef HAVE_PROJ
 #include <proj.h>
 #endif
 
+
 /* geos does not support 3d envelope */
 typedef struct mbr {
        float xmin;
@@ -96,6 +98,9 @@ 11 = MULTIPOLYGON
 
 */
 
+libgeom_export GEOSContextHandle_t libgeom_tls(void);
+#define geoshandle (libgeom_tls())
+
 typedef enum wkb_type {
     // TODO: deprecated        type REMOVE
        //wkbGeometry_mbd = 0,
@@ -129,8 +134,7 @@ typedef struct {
        wkb wkb;
 } geom_geometry;
 
-libgeom_export void libgeom_init(void);
-libgeom_export void libgeom_exit(void);
+libgeom_export gdk_return libgeom_init(void);
 
 #define mbr_nil mbrFromGeos(NULL);
 
diff --git a/geom/monetdb5/geod.c b/geom/monetdb5/geod.c
--- a/geom/monetdb5/geod.c
+++ b/geom/monetdb5/geod.c
@@ -166,8 +166,8 @@ static GeoPoint
 geoPointFromGeom(GEOSGeom geom)
 {
        GeoPoint geo;
-       GEOSGeomGetX(geom, &(geo.lon));
-       GEOSGeomGetY(geom, &(geo.lat));
+       GEOSGeomGetX_r(geoshandle, geom, &(geo.lon));
+       GEOSGeomGetY_r(geoshandle, geom, &(geo.lat));
        return geo;
 }
 
@@ -176,12 +176,12 @@ geoPointFromGeom(GEOSGeom geom)
 static GeoLines
 geoLinesFromGeom(GEOSGeom geom)
 {
-       const GEOSCoordSequence *gcs = GEOSGeom_getCoordSeq(geom);
+       const GEOSCoordSequence *gcs = GEOSGeom_getCoordSeq_r(geoshandle, geom);
        GeoLines geo;
-       geo.pointCount = GEOSGeomGetNumPoints(geom);
+       geo.pointCount = GEOSGeomGetNumPoints_r(geoshandle, geom);
        geo.points = GDKmalloc(sizeof(GeoPoint) * geo.pointCount);
        for (int i = 0; i < geo.pointCount; i++)
-               GEOSCoordSeq_getXY(gcs, i, &geo.points[i].lon, 
&geo.points[i].lat);
+               GEOSCoordSeq_getXY_r(geoshandle, gcs, i, &geo.points[i].lon, 
&geo.points[i].lat);
        geo.bbox = NULL;
        return geo;
 }
@@ -195,8 +195,8 @@ geoPolygonFromGeom(GEOSGeom geom)
 {
        GeoPolygon geo;
        //Get exterior ring GeoLines
-       geo.exteriorRing = 
geoLinesFromGeom((GEOSGeom)GEOSGetExteriorRing(geom));
-       geo.interiorRingsCount = GEOSGetNumInteriorRings(geom);
+       geo.exteriorRing = 
geoLinesFromGeom((GEOSGeom)GEOSGetExteriorRing_r(geoshandle, geom));
+       geo.interiorRingsCount = GEOSGetNumInteriorRings_r(geoshandle, geom);
        //If there are interior rings, allocate space to their GeoLines 
representation
        if (geo.interiorRingsCount > 0)
                //TODO Malloc fail exception?
@@ -205,7 +205,7 @@ geoPolygonFromGeom(GEOSGeom geom)
                geo.interiorRings = NULL;
        //Get interior rings GeoLines
        for (int i = 0; i < geo.interiorRingsCount; i++)
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to