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