[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