[geos-commits] r4060 - in trunk: . capi

svn_geos at osgeo.org svn_geos at osgeo.org
Mon Jul 20 10:25:26 PDT 2015


Author: strk
Date: 2015-07-20 10:25:26 -0700 (Mon, 20 Jul 2015)
New Revision: 4060

Modified:
   trunk/NEWS
   trunk/capi/geos_c.h.in
   trunk/capi/geos_ts_c.cpp
Log:
Extend error and notice notification with threadsafe variants (#663)

Patch by Pepijn Van Eeckhoudt <pepijn at vaneeckhoudt.net>
Tested by Alessandro Furieri <a.furieri at lqt.it>

Signed-off-by: Sandro Santilli <strk at keybit.net>

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2015-07-19 13:04:26 UTC (rev 4059)
+++ trunk/NEWS	2015-07-20 17:25:26 UTC (rev 4060)
@@ -7,7 +7,7 @@
   - GEOS_USE_ONLY_R_API macro support (#695)
   - PHP: WKBReader->read() & WKBWriter::write() methods (Benjamin Morel)
   - RectangleIntersection, GEOSClipByRect (Mika Heiskanen, Sandro Santilli)
-  ...
+  - CAPI: thread-safe message handling API (#663, Pepijn Van Eeckhoudt)
 - Improvements:
   - Speed-up intersection and difference between geometries
     with small bounding box overlap.

Modified: trunk/capi/geos_c.h.in
===================================================================
--- trunk/capi/geos_c.h.in	2015-07-19 13:04:26 UTC (rev 4059)
+++ trunk/capi/geos_c.h.in	2015-07-20 17:25:26 UTC (rev 4060)
@@ -94,8 +94,22 @@
  *
  ************************************************************************/
 
+typedef struct GEOSContextHandle_HS *GEOSContextHandle_t;
+
 typedef void (*GEOSMessageHandler)(const char *fmt, ...);
 
+/*
+ * A GEOS message handler function.
+ *
+ * @param message the message contents
+ * @param userdata the user data pointer that was passed to GEOS when registering this message handler.
+ *
+ *
+ * @see GEOSContext_setErrorMessageHandler
+ * @see GEOSContext_setNoticeMessageHandler
+ */
+typedef void (*GEOSMessageHandler_r)(const char *message, void *userdata);
+
 /* When we're included by geos_c.cpp, those are #defined to the original
  * JTS definitions via preprocessor. We don't touch them to allow the
  * compiler to cross-check the declarations. However, for all "normal"
@@ -138,8 +152,6 @@
     GEOS_WKB_NDR = 1 /* Little Endian */
 };
 
-typedef struct GEOSContextHandle_HS *GEOSContextHandle_t;
-
 typedef void (*GEOSQueryCallback)(void *item, void *userdata);
 
 /************************************************************************
@@ -163,17 +175,54 @@
 /* Cancel a pending interruption request */
 extern void GEOS_DLL GEOS_interruptCancel();
 
-
+/*
+ * @deprecated in 3.5.0
+ *     initialize using GEOS_init_r() and set the message handlers using
+ *     GEOSContext_setNoticeHandler_r and/or GEOSContext_setErrorHandler_r
+ */
 extern GEOSContextHandle_t GEOS_DLL initGEOS_r(
                                     GEOSMessageHandler notice_function,
                                     GEOSMessageHandler error_function);
+/*
+ * @deprecated in 3.5.0 replaced by GEOS_finish_r.
+ */
 extern void GEOS_DLL finishGEOS_r(GEOSContextHandle_t handle);
 
+extern GEOSContextHandle_t GEOS_DLL GEOS_init_r();
+extern void GEOS_DLL GEOS_finish_r(GEOSContextHandle_t handle);
+
+
 extern GEOSMessageHandler GEOS_DLL GEOSContext_setNoticeHandler_r(GEOSContextHandle_t extHandle,
                                                                   GEOSMessageHandler nf);
 extern GEOSMessageHandler GEOS_DLL GEOSContext_setErrorHandler_r(GEOSContextHandle_t extHandle,
                                                                  GEOSMessageHandler ef);
 
+/*
+ * Sets a notice message handler on the given GEOS context.
+ *
+ * @param extHandle the GEOS context
+ * @param nf the message handler
+ * @param userData optional user data pointer that will be passed to the message handler
+ *
+ * @return the previously configured message handler or NULL if no message handler was configured
+ */
+extern GEOSMessageHandler_r GEOS_DLL GEOSContext_setNoticeMessageHandler_r(GEOSContextHandle_t extHandle,
+                                                                           GEOSMessageHandler_r nf,
+                                                                           void *userData);
+
+/*
+ * Sets an error message handler on the given GEOS context.
+ *
+ * @param extHandle the GEOS context
+ * @param ef the message handler
+ * @param userData optional user data pointer that will be passed to the message handler
+ *
+ * @return the previously configured message handler or NULL if no message handler was configured
+ */
+extern GEOSMessageHandler_r GEOS_DLL GEOSContext_setErrorMessageHandler_r(GEOSContextHandle_t extHandle,
+                                                                          GEOSMessageHandler_r ef,
+                                                                          void *userData);
+
 extern const char GEOS_DLL *GEOSversion();
 
 

Modified: trunk/capi/geos_ts_c.cpp
===================================================================
--- trunk/capi/geos_ts_c.cpp	2015-07-19 13:04:26 UTC (rev 4059)
+++ trunk/capi/geos_ts_c.cpp	2015-07-20 17:25:26 UTC (rev 4060)
@@ -72,6 +72,7 @@
 
 // This should go away
 #include <cmath> // finite
+#include <cstdarg>
 #include <cstddef>
 #include <cstdio>
 #include <cstdlib>
@@ -136,14 +137,115 @@
 
 typedef std::auto_ptr<Geometry> GeomAutoPtr;
 
-typedef struct GEOSContextHandleInternal
+typedef struct GEOSContextHandle_HS
 {
     const GeometryFactory *geomFactory;
-    GEOSMessageHandler NOTICE_MESSAGE;
-    GEOSMessageHandler ERROR_MESSAGE;
+    char msgBuffer[1024];
+    GEOSMessageHandler noticeMessageOld;
+    GEOSMessageHandler_r noticeMessageNew;
+    void *noticeData;
+    GEOSMessageHandler errorMessageOld;
+    GEOSMessageHandler_r errorMessageNew;
+    void *errorData;
     int WKBOutputDims;
     int WKBByteOrder;
     int initialized;
+
+    GEOSContextHandle_HS()
+    {
+      memset(msgBuffer, 0, sizeof(msgBuffer));
+      geomFactory = GeometryFactory::getDefaultInstance();
+      WKBOutputDims = 2;
+      WKBByteOrder = getMachineByteOrder();
+      setNoticeHandler(NULL);
+      setErrorHandler(NULL);
+      initialized = 1;
+    }
+
+    GEOSMessageHandler
+    setNoticeHandler(GEOSMessageHandler nf)
+    {
+        GEOSMessageHandler f = noticeMessageOld;
+        noticeMessageOld = nf;
+        noticeMessageNew = NULL;
+        noticeData = NULL;
+
+        return f;
+    }
+
+    GEOSMessageHandler
+    setErrorHandler(GEOSMessageHandler nf)
+    {
+        GEOSMessageHandler f = errorMessageOld;
+        errorMessageOld = nf;
+        errorMessageNew = NULL;
+        errorData = NULL;
+
+        return f;
+    }
+
+    GEOSMessageHandler_r
+    setNoticeHandler(GEOSMessageHandler_r nf, void *userData) {
+        GEOSMessageHandler_r f = noticeMessageNew;
+        noticeMessageOld = NULL;
+        noticeMessageNew = nf;
+        noticeData = userData;
+
+        return f;
+    }
+
+    GEOSMessageHandler_r
+    setErrorHandler(GEOSMessageHandler_r ef, void *userData)
+    {
+        GEOSMessageHandler_r f = errorMessageNew;
+        errorMessageOld = NULL;
+        errorMessageNew = ef;
+        errorData = userData;
+
+        return f;
+    }
+
+    void
+    NOTICE_MESSAGE(string fmt, ...)
+    {
+      if (NULL == noticeMessageOld && NULL == noticeMessageNew) {
+        return;
+      }
+
+      va_list args;
+      va_start(args, fmt);
+      int result = vsnprintf(msgBuffer, sizeof(msgBuffer) - 1, fmt.c_str(), args);
+      va_end(args);
+
+      if (result > 0) {
+        if (noticeMessageOld) {
+          noticeMessageOld("%s", msgBuffer);
+        } else {
+          noticeMessageNew(msgBuffer, noticeData);
+        }
+      }
+    }
+
+    void
+    ERROR_MESSAGE(string fmt, ...)
+    {
+      if (NULL == errorMessageOld && NULL == errorMessageNew) {
+        return;
+      }
+
+      va_list args;
+      va_start(args, fmt);
+      int result = vsnprintf(msgBuffer, sizeof(msgBuffer) - 1, fmt.c_str(), args);
+      va_end(args);
+
+      if (result > 0) {
+        if (errorMessageOld) {
+          errorMessageOld("%s", msgBuffer);
+        } else {
+          errorMessageNew(msgBuffer, errorData);
+        }
+      }
+    }
 } GEOSContextHandleInternal_t;
 
 // CAPI_ItemVisitor is used internally by the CAPI STRtree
@@ -199,30 +301,29 @@
 GEOSContextHandle_t
 initGEOS_r(GEOSMessageHandler nf, GEOSMessageHandler ef)
 {
-    GEOSContextHandleInternal_t *handle = 0;
-    void *extHandle = 0;
+  GEOSContextHandle_t handle = GEOS_init_r();
 
-    extHandle = malloc(sizeof(GEOSContextHandleInternal_t));
-    if (0 != extHandle)
-    {
-        handle = static_cast<GEOSContextHandleInternal_t*>(extHandle);
-        handle->NOTICE_MESSAGE = nf;
-        handle->ERROR_MESSAGE = ef;
-        handle->geomFactory = GeometryFactory::getDefaultInstance();
-        handle->WKBOutputDims = 2;
-        handle->WKBByteOrder = getMachineByteOrder();
-        handle->initialized = 1;
-    }
+  if (0 != handle) {
+      GEOSContext_setNoticeHandler_r(handle, nf);
+      GEOSContext_setErrorHandler_r(handle, ef);
+  }
 
+  return handle;
+}
+
+GEOSContextHandle_t
+GEOS_init_r()
+{
+    GEOSContextHandleInternal_t *handle = new GEOSContextHandleInternal_t();
+
     geos::util::Interrupt::cancel();
 
-    return static_cast<GEOSContextHandle_t>(extHandle);
+    return static_cast<GEOSContextHandle_t>(handle);
 }
 
 GEOSMessageHandler
 GEOSContext_setNoticeHandler_r(GEOSContextHandle_t extHandle, GEOSMessageHandler nf)
 {
-    GEOSMessageHandler f;
     GEOSContextHandleInternal_t *handle = 0;
     handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
     if ( 0 == handle->initialized )
@@ -230,16 +331,12 @@
         return NULL;
     }
 
-    f = handle->NOTICE_MESSAGE;
-    handle->NOTICE_MESSAGE = nf;
-
-    return f;
+    return handle->setNoticeHandler(nf);
 }
 
 GEOSMessageHandler
 GEOSContext_setErrorHandler_r(GEOSContextHandle_t extHandle, GEOSMessageHandler nf)
 {
-    GEOSMessageHandler f;
     GEOSContextHandleInternal_t *handle = 0;
     handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
     if ( 0 == handle->initialized )
@@ -247,20 +344,48 @@
         return NULL;
     }
 
-    f = handle->ERROR_MESSAGE;
-    handle->ERROR_MESSAGE = nf;
+    return handle->setErrorHandler(nf);
+}
 
-    return f;
+GEOSMessageHandler_r
+GEOSContext_setNoticeMessageHandler_r(GEOSContextHandle_t extHandle, GEOSMessageHandler_r nf, void *userData) {
+    GEOSContextHandleInternal_t *handle = 0;
+    handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
+    if ( 0 == handle->initialized )
+    {
+        return NULL;
+    }
+
+    return handle->setNoticeHandler(nf, userData);
 }
 
+GEOSMessageHandler_r
+GEOSContext_setErrorMessageHandler_r(GEOSContextHandle_t extHandle, GEOSMessageHandler_r ef, void *userData)
+{
+    GEOSContextHandleInternal_t *handle = 0;
+    handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
+    if ( 0 == handle->initialized )
+    {
+        return NULL;
+    }
+
+    return handle->setErrorHandler(ef, userData);
+}
+
 void
 finishGEOS_r(GEOSContextHandle_t extHandle)
 {
     // Fix up freeing handle w.r.t. malloc above
-    free(extHandle);
+    delete extHandle;
     extHandle = NULL;
 }
 
+void
+GEOS_finish_r(GEOSContextHandle_t extHandle)
+{
+    finishGEOS_r(extHandle);
+}
+
 void 
 GEOSFree_r (GEOSContextHandle_t extHandle, void* buffer) 
 { 



More information about the geos-commits mailing list