[geos-commits] r3666 - in trunk: . capi include/geos/util src/util tests/unit tests/unit/capi
svn_geos at osgeo.org
svn_geos at osgeo.org
Thu Jun 7 03:07:02 PDT 2012
Author: strk
Date: 2012-06-07 03:07:01 -0700 (Thu, 07 Jun 2012)
New Revision: 3666
Added:
trunk/tests/unit/capi/GEOSInterruptTest.cpp
Modified:
trunk/NEWS
trunk/capi/geos_c.cpp
trunk/capi/geos_c.h.in
trunk/include/geos/util/Interrupt.h
trunk/src/util/Interrupt.cpp
trunk/tests/unit/Makefile.am
Log:
Add support for registering interruption-checking callback.
This is to enhance flexibility of the interruption request model.
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2012-06-06 14:15:13 UTC (rev 3665)
+++ trunk/NEWS 2012-06-07 10:07:01 UTC (rev 3666)
@@ -2,6 +2,7 @@
????-??-??
- New things:
+ - Interruptibility API (C and C++)
- CAPI: GEOSNode (#496) - PHP: Geometry->node
- GeometryPrecisionReducer class
- BufferInputLineSimplifier header exposed (#548)
Modified: trunk/capi/geos_c.cpp
===================================================================
--- trunk/capi/geos_c.cpp 2012-06-06 14:15:13 UTC (rev 3665)
+++ trunk/capi/geos_c.cpp 2012-06-07 10:07:01 UTC (rev 3666)
@@ -116,6 +116,12 @@
}
void
+GEOS_interruptRegisterCallback(GEOSInterruptCallback* cb, void *cbarg)
+{
+ geos::util::Interrupt::registerCallback(cb, cbarg);
+}
+
+void
GEOS_interruptRequest()
{
geos::util::Interrupt::request();
Modified: trunk/capi/geos_c.h.in
===================================================================
--- trunk/capi/geos_c.h.in 2012-06-06 14:15:13 UTC (rev 3665)
+++ trunk/capi/geos_c.h.in 2012-06-07 10:07:01 UTC (rev 3666)
@@ -154,6 +154,14 @@
extern GEOSAllocator GEOS_DLL GEOS_setAllocator(GEOSAllocator nf);
extern GEOSDeallocator GEOS_DLL GEOS_setDeallocator(GEOSDeallocator nf);
+/*
+ * Register an interruption checking callback
+ *
+ * The callback will be invoked _before_ checking for
+ * interruption, so can be used to request it.
+ */
+typedef void (GEOSInterruptCallback)(void *arg);
+extern void GEOS_DLL GEOS_interruptRegisterCallback(GEOSInterruptCallback* cb, void *cbarg);
/* Request safe interruption of operations */
extern void GEOS_DLL GEOS_interruptRequest();
/* Cancel a pending interruption request */
Modified: trunk/include/geos/util/Interrupt.h
===================================================================
--- trunk/include/geos/util/Interrupt.h 2012-06-06 14:15:13 UTC (rev 3665)
+++ trunk/include/geos/util/Interrupt.h 2012-06-07 10:07:01 UTC (rev 3666)
@@ -22,29 +22,64 @@
#define GEOS_CHECK_FOR_INTERRUPTS() geos::util::Interrupt::process()
+/** Used to manage interruption requests and callbacks */
class GEOS_DLL Interrupt {
public:
+ typedef void (Callback)(void *userdata);
+
+ /**
+ * Request interruption of operations
+ *
+ * Operations will be terminated by a GEOSInterrupt
+ * exception at first occasion.
+ */
static void request() { requested = true; }
+ /** Cancel a pending interruption request */
static void cancel() { requested = false; }
+ /** Check if an interruption request is pending */
static bool check() { return requested; }
+ /** \brief
+ * Register a callback that will be invoked
+ * before checking for interruption requests.
+ *
+ * NOTE that interruption request checking may happen
+ * frequently so any callback would better be quick.
+ *
+ * The callback can be used to call Interrupt::request()
+ *
+ */
+ static void registerCallback(Callback *cb, void *arg) { callback = cb; callback_arg = arg; }
+
+ /**
+ * Invoke the callback, if any. Process pending interruption, if any.
+ *
+ */
static void process() {
+ if ( callback ) (*callback)(callback_arg);
if ( requested ) {
requested = false;
interrupt();
}
}
+ /* Perform the actual interruption (simply throw an exception) */
static void interrupt();
private:
+ /* Could these be portably stored in thread-specific space ? */
+
static bool requested;
+ static Callback *callback;
+
+ static void *callback_arg;
+
};
Modified: trunk/src/util/Interrupt.cpp
===================================================================
--- trunk/src/util/Interrupt.cpp 2012-06-06 14:15:13 UTC (rev 3665)
+++ trunk/src/util/Interrupt.cpp 2012-06-07 10:07:01 UTC (rev 3666)
@@ -28,6 +28,8 @@
Interrupt::interrupt() { throw InterruptedException(); }
bool Interrupt::requested = false;
+Interrupt::Callback *Interrupt::callback = 0;
+void *Interrupt::callback_arg = 0;
} // namespace geos::util
} // namespace geos
Modified: trunk/tests/unit/Makefile.am
===================================================================
--- trunk/tests/unit/Makefile.am 2012-06-06 14:15:13 UTC (rev 3665)
+++ trunk/tests/unit/Makefile.am 2012-06-07 10:07:01 UTC (rev 3666)
@@ -107,6 +107,7 @@
capi/GEOSContainsTest.cpp \
capi/GEOSConvexHullTest.cpp \
capi/GEOSDistanceTest.cpp \
+ capi/GEOSInterruptTest.cpp \
capi/GEOSIntersectsTest.cpp \
capi/GEOSWithinTest.cpp \
capi/GEOSSimplifyTest.cpp \
Added: trunk/tests/unit/capi/GEOSInterruptTest.cpp
===================================================================
--- trunk/tests/unit/capi/GEOSInterruptTest.cpp (rev 0)
+++ trunk/tests/unit/capi/GEOSInterruptTest.cpp 2012-06-07 10:07:01 UTC (rev 3666)
@@ -0,0 +1,125 @@
+//
+// Test Suite for C-API custom allocators
+
+#include <tut.hpp>
+// geos
+#include <geos_c.h>
+// std
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <memory>
+
+namespace tut
+{
+ //
+ // Test Group
+ //
+
+ // Common data used in test cases.
+ struct test_capiinterrupt_data
+ {
+ static int alloc_count;
+ static int dealloc_count;
+
+ static void notice(const char *fmt, ...)
+ {
+ std::fprintf( stdout, "NOTICE: ");
+
+ va_list ap;
+ va_start(ap, fmt);
+ std::vfprintf(stdout, fmt, ap);
+ va_end(ap);
+
+ std::fprintf(stdout, "\n");
+ }
+
+ test_capiinterrupt_data()
+ {
+ }
+
+ ~test_capiinterrupt_data()
+ {
+ }
+
+ static void interruptNow(void *)
+ {
+ GEOS_interruptRequest();
+ }
+
+ static void countCalls(void *arg)
+ {
+ int* numcalls = reinterpret_cast<int*>(arg);
+ ++(*numcalls);
+ }
+
+ };
+
+ int test_capiinterrupt_data::alloc_count = 0;
+ int test_capiinterrupt_data::dealloc_count = 0;
+
+ typedef test_group<test_capiinterrupt_data> group;
+ typedef group::object object;
+
+ group test_capiinterrupt_group("capi::GEOSInterrupt");
+
+ //
+ // Test Cases
+ //
+
+ /// Test interrupt callback being called
+ template<>
+ template<>
+ void object::test<1>()
+ {
+ int numcalls = 0;
+ GEOS_interruptRegisterCallback(countCalls, &numcalls);
+
+ initGEOS(notice, notice);
+
+ ensure_equals(numcalls, 0);
+
+ GEOSGeometry *geom1 = GEOSGeomFromWKT("LINESTRING(0 0, 1 0)");
+
+ ensure("GEOSGeomFromWKT failed", 0 != geom1);
+
+ GEOSGeometry *geom2 = GEOSBuffer(geom1, 1, 8);
+
+ ensure("GEOSBufferWithStyle failed", 0 != geom2);
+
+ ensure("interrupt callback never called", numcalls > 0);
+
+ GEOSGeom_destroy(geom1);
+ GEOSGeom_destroy(geom2);
+
+ finishGEOS();
+ }
+
+ /// Test interrupting from callback
+ template<>
+ template<>
+ void object::test<2>()
+ {
+ initGEOS(notice, notice);
+
+ GEOS_interruptRegisterCallback(0, 0); /* unregister */
+
+ GEOSGeometry *geom1 = GEOSGeomFromWKT("LINESTRING(0 0, 1 0)");
+
+ ensure("GEOSGeomFromWKT failed", 0 != geom1);
+
+ GEOS_interruptRegisterCallback(interruptNow, 0);
+ bool interrupted = false;
+ GEOSGeometry *geom2 = GEOSBuffer(geom1, 1, 8);
+ ensure("GEOSBuffer wasn't interrupted", 0 == geom2);
+
+ // TODO: check the actual exception ? (sent to notice() callback)
+
+ GEOSGeom_destroy(geom1);
+
+ finishGEOS();
+ }
+
+
+} // namespace tut
+
More information about the geos-commits
mailing list