[geos-commits] r3631 - in trunk: . capi include/geos/util src/util tests/unit tests/unit/capi

svn_geos at osgeo.org svn_geos at osgeo.org
Wed May 16 08:20:42 EDT 2012


Author: strk
Date: 2012-05-16 05:20:42 -0700 (Wed, 16 May 2012)
New Revision: 3631

Added:
   trunk/include/geos/util/CustomAllocators.h
   trunk/src/util/CustomAllocators.cpp
   trunk/tests/unit/capi/GEOSCustomAllocatorTest.cpp
Modified:
   trunk/NEWS
   trunk/capi/geos_c.cpp
   trunk/capi/geos_c.h.in
   trunk/capi/geos_ts_c.cpp
   trunk/include/geos/util/Makefile.am
   trunk/src/util/Makefile.am
   trunk/tests/unit/Makefile.am
Log:
Allow passing custom memory managment functions (#540)

This is both in the C++ library _and_ the C library.

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2012-05-16 10:29:01 UTC (rev 3630)
+++ trunk/NEWS	2012-05-16 12:20:42 UTC (rev 3631)
@@ -4,6 +4,7 @@
 - New things:
   - CAPI: GEOSNode (#496) - PHP: Geometry->node
   - GeometryPrecisionReducer class
+  - Allow passing custom memory managment functions (#540)
 - C++ API changes:
   - New noding::GeometryNoder class
   - Added BufferOp::setSingleSided 

Modified: trunk/capi/geos_c.cpp
===================================================================
--- trunk/capi/geos_c.cpp	2012-05-16 10:29:01 UTC (rev 3630)
+++ trunk/capi/geos_c.cpp	2012-05-16 12:20:42 UTC (rev 3631)
@@ -26,6 +26,9 @@
 #include <geos/operation/union/CascadedPolygonUnion.h>
 #include <geos/algorithm/distance/DiscreteHausdorffDistance.h>
 
+#include <stdexcept>
+#include <new>
+
 #ifdef _MSC_VER
 #pragma warning(disable : 4099)
 #endif
@@ -114,7 +117,7 @@
 { 
     GEOSFree_r( handle, buffer ); 
 } 
-    
+
 /****************************************************************
 ** relate()-related functions
 ** return 0 = false, 1 = true, 2 = error occured

Modified: trunk/capi/geos_c.h.in
===================================================================
--- trunk/capi/geos_c.h.in	2012-05-16 10:29:01 UTC (rev 3630)
+++ trunk/capi/geos_c.h.in	2012-05-16 12:20:42 UTC (rev 3631)
@@ -137,6 +137,9 @@
 
 typedef void (*GEOSQueryCallback)(void *item, void *userdata);
 
+typedef void * (*GEOSAllocator) (size_t size);
+typedef void   (*GEOSFreer)    (void *ptr);
+
 /************************************************************************
  *
  * Initialization, cleanup, version
@@ -148,7 +151,10 @@
 extern void GEOS_DLL initGEOS(GEOSMessageHandler notice_function,
 	GEOSMessageHandler error_function);
 extern void GEOS_DLL finishGEOS(void);
+extern GEOSAllocator GEOS_DLL GEOS_setAllocator(GEOSAllocator nf);
+extern GEOSFreer GEOS_DLL GEOS_setFreer(GEOSFreer nf);
 
+
 extern GEOSContextHandle_t GEOS_DLL initGEOS_r(
                                     GEOSMessageHandler notice_function,
                                     GEOSMessageHandler error_function);

Modified: trunk/capi/geos_ts_c.cpp
===================================================================
--- trunk/capi/geos_ts_c.cpp	2012-05-16 10:29:01 UTC (rev 3630)
+++ trunk/capi/geos_ts_c.cpp	2012-05-16 12:20:42 UTC (rev 3631)
@@ -58,6 +58,7 @@
 #include <geos/operation/relate/RelateOp.h>
 #include <geos/operation/sharedpaths/SharedPathsOp.h>
 #include <geos/linearref/LengthIndexedLine.h>
+#include <geos/util/CustomAllocators.h>
 #include <geos/util/IllegalArgumentException.h>
 #include <geos/util/UniqueCoordinateArrayFilter.h>
 #include <geos/util/Machine.h>
@@ -156,11 +157,54 @@
 extern "C" const char GEOS_DLL *GEOSjtsport();
 extern "C" char GEOS_DLL *GEOSasText(Geometry *g1);
 
+// --- Custom memory allocators -------------------------------- {
+
+GEOSAllocator geos_alloc = std::malloc;
+GEOSFreer geos_free = std::free; 
+
+GEOSAllocator
+GEOS_setAllocator(GEOSAllocator nf)
+{
+  GEOSAllocator of = geos_alloc;
+  geos_alloc = nf;
+  geos::util::CustomAllocators::setAllocator(geos_alloc);
+  return of;
+}
+
+GEOSFreer
+GEOS_setFreer(GEOSFreer nf)
+{
+  GEOSFreer of = geos_free;
+  geos_free = nf;
+  geos::util::CustomAllocators::setFreer(geos_free);
+  return of;
+}
+
+void*
+operator new (std::size_t size, const std::nothrow_t&) throw () {
+        //cout << "new(" << size << ") called" << endl;
+        return geos_alloc(size);
+}
+
+void operator delete (void *ptr) throw () {
+        //cout << "delete(" << ptr << ") called" << endl;
+        if ( ptr ) geos_free(ptr);
+}
+
+void* operator new (std::size_t size) throw (std::bad_alloc) {
+  if ( void* ret = operator new (size, std::nothrow) ) return ret;
+  throw std::bad_alloc();
+}
+
+// ---------------------------------------------------------------- }
+
+
+
 namespace { // anonymous
 
 char* gstrdup_s(const char* str, const std::size_t size)
 {
-    char* out = static_cast<char*>(std::malloc(size + 1));
+    char* out = static_cast<char*>(geos_alloc(size + 1));
     if (0 != out)
     {
         // as no strlen call necessary, memcpy may be faster than strcpy
@@ -193,7 +237,7 @@
     GEOSContextHandleInternal_t *handle = 0;
     void *extHandle = 0;
 
-    extHandle = std::malloc(sizeof(GEOSContextHandleInternal_t));
+    extHandle = geos_alloc(sizeof(GEOSContextHandleInternal_t));
     if (0 != extHandle)
     {
         handle = static_cast<GEOSContextHandleInternal_t*>(extHandle);
@@ -246,7 +290,7 @@
 finishGEOS_r(GEOSContextHandle_t extHandle)
 {
     // Fix up freeing handle w.r.t. malloc above
-    std::free(extHandle);
+    geos_free(extHandle);
     extHandle = NULL;
 }
 
@@ -255,7 +299,7 @@
 { 
     assert(0 != extHandle);
 
-    std::free(buffer); 
+    geos_free(buffer); 
 } 
 
 //-----------------------------------------------------------
@@ -1240,7 +1284,7 @@
         const std::size_t len = wkbstring.length();
 
         unsigned char* result = 0;
-        result = static_cast<unsigned char*>(std::malloc(len));
+        result = static_cast<unsigned char*>(geos_alloc(len));
         if (0 != result)
         {
             std::memcpy(result, wkbstring.c_str(), len);
@@ -4732,7 +4776,7 @@
         const std::size_t len = wkbstring.length();
 
         unsigned char *result = NULL;
-        result = (unsigned char*) std::malloc(len);
+        result = (unsigned char*) geos_alloc(len);
         std::memcpy(result, wkbstring.c_str(), len);
         *size = len;
         return result;
@@ -4776,7 +4820,7 @@
         const std::size_t len = wkbstring.length();
 
         unsigned char *result = NULL;
-        result = (unsigned char*) std::malloc(len);
+        result = (unsigned char*) geos_alloc(len);
         std::memcpy(result, wkbstring.c_str(), len);
         *size = len;
         return result;

Added: trunk/include/geos/util/CustomAllocators.h
===================================================================
--- trunk/include/geos/util/CustomAllocators.h	                        (rev 0)
+++ trunk/include/geos/util/CustomAllocators.h	2012-05-16 12:20:42 UTC (rev 3631)
@@ -0,0 +1,30 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Sandro Santilli <strk at keybit.net>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation. 
+ * See the COPYING file for more information.
+ *
+ **********************************************************************/
+
+#include <cstdlib> // size_t
+
+namespace geos {
+namespace util {
+namespace CustomAllocators {
+
+  typedef void * (*GEOSAllocator) (std::size_t size);
+  GEOSAllocator setAllocator(GEOSAllocator nf);
+
+  typedef void   (*GEOSFreer)    (void *ptr);
+  GEOSFreer setFreer(GEOSFreer nf);
+
+}
+}
+}
+

Modified: trunk/include/geos/util/Makefile.am
===================================================================
--- trunk/include/geos/util/Makefile.am	2012-05-16 10:29:01 UTC (rev 3630)
+++ trunk/include/geos/util/Makefile.am	2012-05-16 12:20:42 UTC (rev 3631)
@@ -10,6 +10,7 @@
 geos_HEADERS = \
     Assert.h \
     AssertionFailedException.h \
+    CustomAllocators.h \
     CoordinateArrayFilter.h \
     GeometricShapeFactory.h \
     GEOSException.h \

Added: trunk/src/util/CustomAllocators.cpp
===================================================================
--- trunk/src/util/CustomAllocators.cpp	                        (rev 0)
+++ trunk/src/util/CustomAllocators.cpp	2012-05-16 12:20:42 UTC (rev 3631)
@@ -0,0 +1,59 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Sandro Santilli <strk at keybit.net>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation. 
+ * See the COPYING file for more information.
+ *
+ **********************************************************************/
+
+#include <geos/util/CustomAllocators.h>
+
+#include <new>
+#include <iostream>
+#include <cstdlib>
+
+namespace geos {
+namespace util {
+namespace CustomAllocators {
+
+GEOSAllocator geos_alloc = std::malloc;
+GEOSFreer geos_free = std::free;
+
+GEOSAllocator
+setAllocator(GEOSAllocator nf)
+{
+  GEOSAllocator of = geos_alloc;
+  geos_alloc = nf;
+  return of;
+}
+
+GEOSFreer
+setFreer(GEOSFreer nf)
+{
+  GEOSFreer of = geos_free;
+  geos_free = nf;
+  return of;
+}
+
+}
+}
+}
+
+
+void*
+operator new (std::size_t size, const std::nothrow_t&) throw () {
+        //std::cout << "...new(" << size << ") called" << std::endl;
+        return std::malloc(size);
+}
+
+void operator delete (void *ptr) throw () {
+        //std::cout << "...delete(" << ptr << ") called" << std::endl;
+        if ( ptr ) std::free(ptr);
+}
+

Modified: trunk/src/util/Makefile.am
===================================================================
--- trunk/src/util/Makefile.am	2012-05-16 10:29:01 UTC (rev 3630)
+++ trunk/src/util/Makefile.am	2012-05-16 12:20:42 UTC (rev 3631)
@@ -9,6 +9,7 @@
 
 libutil_la_SOURCES = \
 	Assert.cpp \
+	CustomAllocators.cpp \
 	GeometricShapeFactory.cpp \
 	math.cpp \
 	Profiler.cpp 

Modified: trunk/tests/unit/Makefile.am
===================================================================
--- trunk/tests/unit/Makefile.am	2012-05-16 10:29:01 UTC (rev 3630)
+++ trunk/tests/unit/Makefile.am	2012-05-16 12:20:42 UTC (rev 3631)
@@ -102,6 +102,7 @@
 	simplify/TopologyPreservingSimplifierTest.cpp \
 	util/UniqueCoordinateArrayFilterTest.cpp \
 	capi/GEOSCoordSeqTest.cpp \
+	capi/GEOSCustomAllocatorTest.cpp \
 	capi/GEOSGeomFromWKBTest.cpp \
 	capi/GEOSGeomToWKTTest.cpp \
 	capi/GEOSContainsTest.cpp \

Added: trunk/tests/unit/capi/GEOSCustomAllocatorTest.cpp
===================================================================
--- trunk/tests/unit/capi/GEOSCustomAllocatorTest.cpp	                        (rev 0)
+++ trunk/tests/unit/capi/GEOSCustomAllocatorTest.cpp	2012-05-16 12:20:42 UTC (rev 3631)
@@ -0,0 +1,110 @@
+// 
+// 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_capicustomallocators_data
+    {
+        static int alloc_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");
+        }
+
+        static void *t_alloc(size_t sz)
+        {
+            ++alloc_count;
+            void *ret = std::malloc(sz);
+            //notice("t_alloc(%d) returning %p", sz, ret);
+            return ret;
+        }
+
+        static void t_free(void *ptr)
+        {
+            //notice("t_free(%p)", ptr);
+            --alloc_count;
+            std::free(ptr);
+        }
+
+        test_capicustomallocators_data()
+        {
+            GEOS_setAllocator(t_alloc);
+            GEOS_setFreer(t_free);
+
+            alloc_count = 0;
+        }       
+
+        ~test_capicustomallocators_data()
+        {
+        }
+
+    };
+
+    int test_capicustomallocators_data::alloc_count = 0;
+
+    typedef test_group<test_capicustomallocators_data> group;
+    typedef group::object object;
+
+    group test_capicustomallocators_group("capi::GEOSCustomAllocators");
+
+    //
+    // Test Cases
+    //
+
+    /// init and finish
+    template<>
+    template<>
+    void object::test<1>()
+    {
+        alloc_count = 0;
+
+        initGEOS(notice, notice);
+        finishGEOS();
+
+        ensure_equals(alloc_count, 0);
+    }
+
+    /// WKTReader 
+    template<>
+    template<>
+    void object::test<2>()
+    {
+        alloc_count = 0;
+
+        initGEOS(notice, notice);
+
+        GEOSWKTReader* reader = GEOSWKTReader_create();
+        GEOSGeometry* g = GEOSWKTReader_read(reader, "POINT(0 0)");
+        GEOSGeom_destroy(g);
+        GEOSWKTReader_destroy(reader);
+
+        finishGEOS();
+
+        ensure_equals(alloc_count, 0);
+    }
+
+
+} // namespace tut
+



More information about the geos-commits mailing list