[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