[MOAB-dev] r3570 - MOAB/trunk/tools/iMesh

kraftche at cae.wisc.edu kraftche at cae.wisc.edu
Fri Mar 5 19:22:59 CST 2010


Author: kraftche
Date: 2010-03-05 19:22:59 -0600 (Fri, 05 Mar 2010)
New Revision: 3570

Modified:
   MOAB/trunk/tools/iMesh/iMeshP_MOAB.cpp
   MOAB/trunk/tools/iMesh/iMesh_MOAB.cpp
   MOAB/trunk/tools/iMesh/iMesh_MOAB.hpp
Log:
Free allocated arrays in any iGeom call that returns something other than 
iBase_SUCCESS (a few in iMesh_MOAB, many in iMeshP_MOAB).


Details:

Replace CHECK_SIZE macro with new macro: ALLOC_CHECK_ARRAY.  The argument
list for the new macro is a lot simpler: the type is inferred from
the array type and all array arguments (pointer, allocated, size) are
inferred from the array name. Thus:
  *adjacency_table_size = 16;
  CHECK_SIZE(*adjacency_table, *adjacency_table_allocated,
             *adjacency_table_size, int, iBase_MEMORY_ALLOCATION_FAILED);
becomes:
  ALLOC_CHECK_ARRAY(adjacency_table, 16);

However, the big difference is that if (and only if) ALLOC_CHECK_ARRAY 
allocated the array, then it will free it when the macro call goes out of 
scope (typically when returning from the function) unless KEEP_ARRAY(name) 
is called.  Thus one can safely write code like:

  ALLOC_CHECK_ARRAY(uv, 2*count);
  for (...) {
    ...
    if (error)
      RETURN(iBase_FAILURE);
    ...
    if (iBase_SUCCESS != *err)
      return;
  }
  KEEP_ARRAY(uv);
  RETURN(iBase_SUCCESS);
  
And even the hairy cases like the memory allocation for the second of
two arrays failing is handled correctly.

Also, provide the macro ALLOC_CHECK_ARRAY_NOFAIL for convenience.  It
is equivalent to consecutive calls to ALLOC_CHECK_ARRAY and KEEP_ARRAY.


Modified: MOAB/trunk/tools/iMesh/iMeshP_MOAB.cpp
===================================================================
--- MOAB/trunk/tools/iMesh/iMeshP_MOAB.cpp	2010-03-06 01:10:21 UTC (rev 3569)
+++ MOAB/trunk/tools/iMesh/iMeshP_MOAB.cpp	2010-03-06 01:22:59 UTC (rev 3570)
@@ -140,40 +140,9 @@
 
 /********************* ITAPS arrays **************************/
 
-// Access this method using ALLOCATE_ARRAY macro, rather than callind directly.
-template <typename ArrType> inline bool
-allocate_itaps_array( ArrType*& array, int& allocated, int& size, int requested )
-{
-  size = requested;
-  if (allocated) {
-    return (allocated >= requested);
-  }
-  else {
-    array = (ArrType*)malloc( requested * sizeof(ArrType) );
-    allocated = requested;
-    return (array != 0);
-  }
-}
-
-// For use by ALLOCATE_ARRAY macro
-inline int allocate_itaps_array_failed()
-{
-  strcpy( iMesh_LAST_ERROR.description, 
-          "Insufficient allocated array size or insufficient "
-          "memory to allocate array." );
-  iMesh_LAST_ERROR.error_type = iBase_MEMORY_ALLOCATION_FAILED;
-  return iBase_MEMORY_ALLOCATION_FAILED;
-}
-
-// If ITAPS array is NULL, allocate it to the requested size, otherwise
-// verify that it can hold at least SIZE values.
-#define ALLOCATE_ARRAY( NAME, SIZE ) \
-  if (!allocate_itaps_array( *NAME, *NAME##_allocated, *NAME##_size, (SIZE) )) \
-    RETURN(allocate_itaps_array_failed())
-
 // Handle returning MBRange in ITAPS array (do ALLOCATE_ARRAY and copy).
 #define MBRANGE_TO_ITAPS_ARRAY( RANGE, NAME ) do { \
-  ALLOCATE_ARRAY( NAME, (RANGE).size() ); \
+  ALLOC_CHECK_ARRAY_NOFAIL( NAME, (RANGE).size() ); \
   std::copy( (RANGE).begin(), (RANGE).end(), itaps_cast<MBEntityHandle*>(*(NAME)) ); \
   } while (false)
 
@@ -342,13 +311,14 @@
 {
   MBErrorCode rval;
   MBParallelComm* pcomm = PCOMM;
-  ALLOCATE_ARRAY( part_ids, part_handles_size );
+  ALLOC_CHECK_ARRAY( part_ids, part_handles_size );
   for (int i = 0; i < part_handles_size; ++i) {
     int id;
     rval = pcomm->get_part_id( itaps_cast<MBEntityHandle>(part_handles[i]), id );
     (*part_ids)[i] = id;
     CHKERR(rval,"error getting part id");
   }
+  KEEP_ARRAY(part_ids);
   RETURN(iBase_SUCCESS);
 }
 
@@ -364,13 +334,14 @@
 {
   MBErrorCode rval;
   MBParallelComm* pcomm = PCOMM;
-  ALLOCATE_ARRAY( part_handles, part_ids_size );
+  ALLOC_CHECK_ARRAY( part_handles, part_ids_size );
   for (int i = 0; i < part_ids_size; ++i) {
     MBEntityHandle handle;
     rval = pcomm->get_part_handle( part_ids[i], handle );
     CHKERR(rval,"error getting part handle");
     (*part_handles)[i] = itaps_cast<iMeshP_PartHandle>(handle);
   }
+  KEEP_ARRAY(part_handles);
   RETURN(iBase_SUCCESS);
 }
 
@@ -430,7 +401,7 @@
   for (i = pcomms.begin(); i != pcomms.end(); ++i)
     if ((*i)->get_partitioning())
       ++count;
-  ALLOCATE_ARRAY( partition_handle, count );
+  ALLOC_CHECK_ARRAY_NOFAIL( partition_handle, count );
   
   *partition_handle_size = 0;
   for (i = pcomms.begin(); i != pcomms.end(); ++i)
@@ -507,12 +478,13 @@
   if (!pcomm)
     ERROR (iBase_FAILURE,"No PComm");
   
-  ALLOCATE_ARRAY( rank, part_ids_size );
+  ALLOC_CHECK_ARRAY( rank, part_ids_size );
   MBErrorCode rval = MB_SUCCESS;
   for (int i = 0; i < part_ids_size; ++i) {
     rval = pcomm->get_part_owner( part_ids[i], (*rank)[i] );
     CHKERR(rval,"PComm::get_part_owner failed");
   }
+  KEEP_ARRAY(rank);
   RETURN(iBase_SUCCESS);
 }
 
@@ -635,7 +607,7 @@
   if (!pcomm) 
     ERROR (iBase_FAILURE,"No PComm");
 
-  ALLOCATE_ARRAY( num_part_nbors, part_handles_size );
+  ALLOC_CHECK_ARRAY( num_part_nbors, part_handles_size );
   
   int n, neighbors[MAX_SHARING_PROCS];
   MBErrorCode rval;
@@ -646,6 +618,7 @@
     (*num_part_nbors)[i] = n;
   }
   
+  KEEP_ARRAY(num_part_nbors);
   RETURN(iBase_SUCCESS);
 }
 
@@ -685,7 +658,7 @@
   if (!pcomm) 
     ERROR (iBase_FAILURE,"No PComm");
 
-  ALLOCATE_ARRAY( num_part_nbors, part_handles_size );
+  ALLOC_CHECK_ARRAY( num_part_nbors, part_handles_size );
   
   std::vector<int> all_neighbors;
   int n, pnbor[MAX_SHARING_PROCS];
@@ -698,9 +671,10 @@
     std::copy( pnbor, pnbor+n, std::back_inserter(all_neighbors) );
   }
   
-  ALLOCATE_ARRAY( nbor_part_ids, all_neighbors.size() );
+  ALLOC_CHECK_ARRAY_NOFAIL( nbor_part_ids, all_neighbors.size() );
   memcpy( *nbor_part_ids, &all_neighbors[0], sizeof(int)*all_neighbors.size() );
   
+  KEEP_ARRAY(num_part_nbors);
   RETURN(iBase_SUCCESS);
 }
 
@@ -1059,8 +1033,8 @@
   }
   
     // get adjacencies
-  ALLOCATE_ARRAY( adj_entity_handles, num_adj );
-  ALLOCATE_ARRAY( offset, r.size() );
+  ALLOC_CHECK_ARRAY( adj_entity_handles, num_adj );
+  ALLOC_CHECK_ARRAY( offset, r.size() );
   int arr_pos = 0;
   int* offset_iter = *offset;
   for (MBRange::iterator i = r.begin(); i != r.end(); ++i)  {
@@ -1085,6 +1059,11 @@
                            in_entity_set_allocated,
                            in_entity_set_size,
                            err );
+  
+  if (iBase_SUCCESS == *err) {
+    KEEP_ARRAY(adj_entity_handles);
+    KEEP_ARRAY(offset);
+  }
 }
 
 void iMeshP_initEntIter( iMesh_Instance instance,
@@ -1153,7 +1132,7 @@
     ERROR (iBase_FAILURE,"No PComm");
   
   int id;
-  ALLOCATE_ARRAY( part_ids, entity_handles_size );
+  ALLOC_CHECK_ARRAY( part_ids, entity_handles_size );
   MBErrorCode rval = MB_SUCCESS;
   for (int i = 0; i < entity_handles_size; ++i) {
     MBEntityHandle h = itaps_cast<MBEntityHandle>(entity_handles[i]);
@@ -1161,6 +1140,7 @@
     (*part_ids)[i] = id;
     CHKERR(rval,"Failet get part owner");
   }
+  KEEP_ARRAY(part_ids);
   RETURN(iBase_SUCCESS);
 }
   
@@ -1197,7 +1177,7 @@
   rval = pcomm->get_part_id( itaps_cast<MBEntityHandle>(part_handle), id );
   CHKERR(rval,"error getting part id");
   
-  ALLOCATE_ARRAY( is_owner, entity_handles_size );
+  ALLOC_CHECK_ARRAY( is_owner, entity_handles_size );
   *is_owner_size = entity_handles_size;
   
   int owner;
@@ -1207,6 +1187,7 @@
     (*is_owner)[i] = (owner == id);
   }
   
+  KEEP_ARRAY(is_owner);
   RETURN(iBase_SUCCESS);
 }
 
@@ -1245,7 +1226,7 @@
                                          &pstatus[0]); 
   CHKERR(result,"error getting pstatus_tag");
 
-  ALLOCATE_ARRAY( par_status, entity_handles_size );
+  ALLOC_CHECK_ARRAY( par_status, entity_handles_size );
   for (int i = 0; i < entity_handles_size; i++) {
     if (!pstatus[i]) 
       (*par_status)[i] = iMeshP_INTERNAL;
@@ -1255,6 +1236,7 @@
       (*par_status)[i] = iMeshP_BOUNDARY;
   }
 
+  KEEP_ARRAY(par_status);
   RETURN(iBase_SUCCESS);
 }
 
@@ -1293,7 +1275,7 @@
                               itaps_cast<MBEntityHandle>(entity_handle),
                               ids, num_ids ); 
   CHKERR(rval,"MBParallelComm::get_sharing_parts failed");
-  ALLOCATE_ARRAY( part_ids, num_ids );
+  ALLOC_CHECK_ARRAY_NOFAIL( part_ids, num_ids );
   std::copy( ids, ids+num_ids, *part_ids );
   RETURN (iBase_SUCCESS);
 }
@@ -1321,8 +1303,8 @@
                               itaps_cast<MBEntityHandle>(entity_handle),
                               ids, num_ids, handles ); 
   CHKERR(rval,"MBParallelComm::get_sharing_parts failed");
-  ALLOCATE_ARRAY( part_ids, num_ids );
-  ALLOCATE_ARRAY( copies_entity_handles, num_ids );
+  ALLOC_CHECK_ARRAY_NOFAIL( part_ids, num_ids );
+  ALLOC_CHECK_ARRAY_NOFAIL( copies_entity_handles, num_ids );
   for (int i = 0; i < num_ids; ++i) {
     (*part_ids)[i] = ids[i];
     (*copies_entity_handles)[i] = itaps_cast<iBase_EntityHandle>(handles[i]);
@@ -1730,7 +1712,7 @@
 
     MBRange part_sets;
   
-    ALLOCATE_ARRAY( part_handles, pc->partition_sets().size() );
+    ALLOC_CHECK_ARRAY_NOFAIL( part_handles, pc->partition_sets().size() );
     MBRange::iterator rit;
     int i;
     for (i = 0, rit = pc->partition_sets().begin(); 

Modified: MOAB/trunk/tools/iMesh/iMesh_MOAB.cpp
===================================================================
--- MOAB/trunk/tools/iMesh/iMesh_MOAB.cpp	2010-03-06 01:10:21 UTC (rev 3569)
+++ MOAB/trunk/tools/iMesh/iMesh_MOAB.cpp	2010-03-06 01:22:59 UTC (rev 3570)
@@ -52,34 +52,6 @@
 MBErrorCode create_int_ents(MBInterface *instance,
                             MBRange &from_ents,
                             const MBEntityHandle* in_set = 0);
-
-#define CHECK_SIZE(array, allocated, size, type, retval)  \
-  if (0 != allocated && NULL != array && allocated < (size)) {\
-    iMesh_processError(iBase_MEMORY_ALLOCATION_FAILED, \
-          "Allocated array not large enough to hold returned contents.");\
-    RETURN(iBase_MEMORY_ALLOCATION_FAILED);\
-  }\
-  if ((size) && ((allocated) == 0 || NULL == (array))) {\
-    array = (type*)malloc((size)*sizeof(type));\
-    allocated=(size);\
-    if (NULL == array) {iMesh_processError(iBase_MEMORY_ALLOCATION_FAILED, \
-          "Couldn't allocate array.");RETURN(iBase_MEMORY_ALLOCATION_FAILED); }\
-  }
-// TAG_CHECK_SIZE is like CHECK_SIZE except it checks for and makes the allocated memory
-// size a multiple of sizeof(void*), and the pointer is assumed to be type char*
-#define TAG_CHECK_SIZE(array, allocated, size)  \
-  if (0 != allocated && NULL != array && allocated < (size)) {\
-    iMesh_processError(iBase_MEMORY_ALLOCATION_FAILED, \
-          "Allocated array not large enough to hold returned contents.");\
-    RETURN(iBase_MEMORY_ALLOCATION_FAILED);\
-  }\
-  if ((size) && (NULL == (array) || (allocated) == 0)) {\
-    allocated=(size); \
-    if (allocated%sizeof(void*) != 0) allocated=((size)/sizeof(void*)+1)*sizeof(void*);\
-    array = (char*)malloc(allocated); \
-    if (NULL == array) {iMesh_processError(iBase_MEMORY_ALLOCATION_FAILED, \
-          "Couldn't allocate array.");RETURN(iBase_MEMORY_ALLOCATION_FAILED); }\
-  }
 #define HANDLE_ARRAY_PTR(array) reinterpret_cast<MBEntityHandle*>(array)
 #define CONST_HANDLE_ARRAY_PTR(array) reinterpret_cast<const MBEntityHandle*>(array)
 #define TAG_HANDLE(handle) reinterpret_cast<MBTag>(handle)
@@ -388,9 +360,7 @@
                           /*inout*/ int* adjacency_table_allocated, 
                           /*out*/ int* adjacency_table_size, int *err)
   {
-    *adjacency_table_size = 16;
-    CHECK_SIZE(*adjacency_table, *adjacency_table_allocated,
-               *adjacency_table_size, int, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY_NOFAIL(adjacency_table, 16);
     memcpy(*adjacency_table, MBimesh->AdjTable, 16*sizeof(int));
     RETURN(iBase_SUCCESS);
   }
@@ -465,7 +435,7 @@
   {
 
       // make sure we can hold them all
-    CHECK_SIZE(*coords, *coords_allocated, 3*vertex_handles_size, double, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY(coords, 3*vertex_handles_size);
   
       // now get all the coordinates
       // coords will come back interleaved by default
@@ -493,9 +463,8 @@
         *z = *c_iter; ++z; ++c_iter;
       }
     }
-
-    *coords_size = 3*vertex_handles_size;
   
+    KEEP_ARRAY(coords);
     RETURN(iBase_SUCCESS);
   }
 
@@ -552,8 +521,7 @@
       // check the size of the destination array
     int expected_size = (this_it->requestedSize < (int)this_it->iteratorRange.size() ? 
                          this_it->requestedSize : this_it->iteratorRange.size());
-    CHECK_SIZE(*entity_handles, *entity_handles_allocated, expected_size,
-               iBase_EntityHandle, false);
+    ALLOC_CHECK_ARRAY_NOFAIL(entity_handles, expected_size);
   
     int i = 0;
     while (i < this_it->requestedSize && this_it->currentPos != this_it->iteratorRange.end())
@@ -599,8 +567,7 @@
                            /*out*/ int* topology_size, int *err) 
   {
       // go through each entity and look up its type
-    CHECK_SIZE(*topology, *topology_allocated, entity_handles_size, 
-               int, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY_NOFAIL(topology, entity_handles_size);
 
     for (int i = 0; i < entity_handles_size; i++)
       (*topology)[i] = 
@@ -619,8 +586,7 @@
                            /*out*/ int* etype_size, int *err) 
   {
       // go through each entity and look up its type
-    CHECK_SIZE(*etype, *etype_allocated, entity_handles_size, 
-               int, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY_NOFAIL(etype, entity_handles_size);
 
     for (int i = 0; i < entity_handles_size; i++)
       (*etype)[i] = 
@@ -644,8 +610,7 @@
   {
     MBErrorCode result = MB_SUCCESS;
 
-    CHECK_SIZE(*offset, *offset_allocated, entity_handles_size+1, 
-               int, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY(offset, entity_handles_size+1);
   
     const MBEntityHandle* entity_iter = (const MBEntityHandle*)entity_handles;
     const MBEntityHandle* const entity_end = entity_iter + entity_handles_size;
@@ -677,7 +642,11 @@
       if (iBase_VERTEX == entity_type_requested &&
           TYPE_FROM_HANDLE(*entity_iter) != MBPOLYHEDRON) {
         result = MBI->get_connectivity(*entity_iter, connect, num_connect, false, &conn_storage);
-        CHKERR(result, "iMesh_getEntArrAdj: trouble getting adjacency list.");
+        if (MB_SUCCESS != result) {
+          if (allocated_array)
+            free(array);
+          ERROR(result, "iMesh_getEntArrAdj: trouble getting adjacency list.");
+        }
       }
       else if (iBase_ALL_TYPES == entity_type_requested) {
         adj_ents.clear();
@@ -685,7 +654,11 @@
           if (MBCN::Dimension(TYPE_FROM_HANDLE(*entity_iter)) == dim)
             continue;
           result = MBI->get_adjacencies( entity_iter, 1, dim, false, adj_ents, MBInterface::UNION );
-          CHKERR(result, "iMesh_getEntArrAdj: trouble getting adjacency list.");
+          if (MB_SUCCESS != result) {
+            if (allocated_array)
+              free(array);
+            ERROR(result, "iMesh_getEntArrAdj: trouble getting adjacency list.");
+          }
         }
         connect = &adj_ents[0];
         num_connect = adj_ents.size();
@@ -694,7 +667,11 @@
         adj_ents.clear();
         result = MBI->get_adjacencies( entity_iter, 1, 
                                        entity_type_requested, false, adj_ents );
-        CHKERR(result, "iMesh_getEntArrAdj: trouble getting adjacency list.");
+        if (MB_SUCCESS != result) {
+          if (allocated_array)
+            free(array);
+          ERROR(result, "iMesh_getEntArrAdj: trouble getting adjacency list.");
+        }
         connect = &adj_ents[0];
         num_connect = adj_ents.size();
       }
@@ -726,7 +703,6 @@
       prev_off += num_connect;
     }
     *off_iter = prev_off;
-    *offset_size = entity_handles_size+1;
     *adjacentEntityHandles_size = prev_off;
 
     if (*adjacentEntityHandles_size > array_alloc) {
@@ -737,6 +713,7 @@
       *adjacentEntityHandles_allocated = array_alloc;
     }
 
+    KEEP_ARRAY(offset);
     RETURN(iBase_SUCCESS);
   }
 
@@ -755,8 +732,7 @@
   {
     MBErrorCode result = MB_SUCCESS;
 
-    CHECK_SIZE(*offset, *offset_allocated, entity_handles_size+1, 
-               int, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY(offset, entity_handles_size+1 );
   
     const MBEntityHandle* entity_iter = (const MBEntityHandle*)entity_handles;
     const MBEntityHandle* const entity_end = entity_iter + entity_handles_size;
@@ -782,14 +758,11 @@
     }
     *off_iter = prev_off;
 
-    CHECK_SIZE(*adj_entity_handles, *adj_entity_handles_allocated, 
-               (int)all_adj_ents.size(), 
-               iBase_EntityHandle, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY_NOFAIL(adj_entity_handles, all_adj_ents.size() );
     memcpy(*adj_entity_handles, &all_adj_ents[0], 
            sizeof(MBEntityHandle)*all_adj_ents.size() );
 
-    *adj_entity_handles_size = all_adj_ents.size();
-    *offset_size = entity_handles_size+1;
+    KEEP_ARRAY(offset);
     RETURN(iBase_SUCCESS);
   }
 
@@ -1006,8 +979,7 @@
                                                     sets, 
                                                     std::max( num_hops, 0 ) );
     CHKERR(rval, "iMesh_entitysetGetEntitySets: problem getting entities by type.");
-    CHECK_SIZE(*contained_entset_handles, *contained_entset_handles_allocated,
-               (int)sets.size(), iBase_EntitySetHandle, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY_NOFAIL(contained_entset_handles, sets.size() );
 
     std::copy( sets.begin(), sets.end(), (MBEntityHandle*)*contained_entset_handles );
     *contained_entset_handles_size = sets.size();
@@ -1104,8 +1076,7 @@
 
   {
     MBEntityHandle set = ENTITY_HANDLE(containing_set);
-    CHECK_SIZE(*is_contained, *is_contained_allocated,
-               (int)num_entity_handles, int, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY_NOFAIL(is_contained, num_entity_handles);
     *is_contained_size = num_entity_handles;
     
     if (containing_set) {
@@ -1218,15 +1189,12 @@
       (ENTITY_HANDLE(from_entity_set), children, num_hops);
 
     CHKERR(result,"ERROR getChildren failed.");
-    CHECK_SIZE(*entity_set_handles, *entity_set_handles_allocated,
-               (int)children.size(), iBase_EntitySetHandle, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY_NOFAIL(entity_set_handles, children.size());
 
     MBEntityHandle *ents = HANDLE_ARRAY_PTR(*entity_set_handles);
       // use a memcpy for efficiency
     memcpy(ents, &children[0], children.size()*sizeof(MBEntityHandle));
 
-    *entity_set_handles_size = children.size();
-
     RETURN(iBase_SUCCESS);
   }
 
@@ -1244,15 +1212,12 @@
 
     CHKERR(result,"ERROR getParents failed.");
 
-    CHECK_SIZE(*entity_set_handles, *entity_set_handles_allocated,
-               (int)parents.size(), iBase_EntitySetHandle, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY_NOFAIL(entity_set_handles, parents.size());
 
     MBEntityHandle *ents = HANDLE_ARRAY_PTR(*entity_set_handles);
       // use a memcpy for efficiency
     memcpy(ents, &parents[0], parents.size()*sizeof(MBEntityHandle));
 
-    *entity_set_handles_size = parents.size();
-
     RETURN(iBase_SUCCESS);
   }
 
@@ -1298,8 +1263,7 @@
     }
 
       // if there aren't any elements in the array, allocate it
-    CHECK_SIZE(*new_vertex_handles, *new_vertex_handles_allocated,
-               num_verts, iBase_EntityHandle, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY(new_vertex_handles, num_verts);
   
       // make the entities
     MBEntityHandle *new_verts = HANDLE_ARRAY_PTR(*new_vertex_handles);
@@ -1309,8 +1273,7 @@
       CHKERR(result, "iMesh_createVtxArr: couldn't create vertex.");
     }  
 
-    *new_vertex_handles_size = new_coords_size/3;
-
+    KEEP_ARRAY(new_vertex_handles);
     RETURN(iBase_SUCCESS);
   }
                                                    
@@ -1347,12 +1310,12 @@
     }
 
       // if there aren't any elements in the array, allocate it
-    CHECK_SIZE(*new_entity_handles, *new_entity_handles_allocated,
-               num_ents, iBase_EntityHandle, iBase_MEMORY_ALLOCATION_FAILED);
+      
+      // This function is poorly defined.  We have to return allocated
+      // arrays even if we fail.
+    ALLOC_CHECK_ARRAY_NOFAIL(new_entity_handles, num_ents);
+    ALLOC_CHECK_ARRAY_NOFAIL(status, num_ents);
   
-    CHECK_SIZE(*status, *status_allocated, num_ents, 
-               int, iBase_MEMORY_ALLOCATION_FAILED);
-  
       // make the entities
     MBEntityHandle *new_ents = HANDLE_ARRAY_PTR(*new_entity_handles);
 
@@ -1644,19 +1607,15 @@
     MBErrorCode result = MBI->tag_get_size(tag, tag_size);
     CHKERR(result, "iMesh_getEntSetData: couldn't get tag size.");
  
-    TAG_CHECK_SIZE(*tag_value, *tag_value_allocated, tag_size);
-
+    ALLOC_CHECK_TAG_ARRAY(tag_value, tag_size);
+ 
     if (eh == 0)
       result = MBI->tag_get_data(tag, NULL, 0, *tag_value);
     else
       result = MBI->tag_get_data(tag, &eh, 1, *tag_value);
 
-    if (MB_SUCCESS != result) {
-      ERROR(result, "iMesh_getEntSetData didn't succeed.");
-    }
-    else
-      *tag_value_size = tag_size;
-  
+    CHKERR(result, "iMesh_getEntSetData didn't succeed.");
+    KEEP_ARRAY(tag_value);
     RETURN(iBase_SUCCESS);
   }
 
@@ -1717,8 +1676,7 @@
     CHKERR(result, "iMesh_entitysetGetAllTagHandles failed.");
  
       // now put those tag handles into sidl array
-    CHECK_SIZE(*tag_handles, *tag_handles_allocated, 
-               (int)all_tags.size(), iBase_TagHandle, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY_NOFAIL(tag_handles, all_tags.size());
     memcpy(*tag_handles, &all_tags[0], all_tags.size()*sizeof(MBTag));
 
     *tag_handles_size = (int) all_tags.size();
@@ -1829,8 +1787,7 @@
       RETURN(iBase_SUCCESS);
     }
   
-    TAG_CHECK_SIZE(*tag_values, *tag_values_allocated, 
-                   tag_size * entity_handles_size);
+    ALLOC_CHECK_TAG_ARRAY(tag_values, tag_size * entity_handles_size);
 
     result = MBI->tag_get_data(tag, ents, entity_handles_size,
                                *tag_values);
@@ -1851,7 +1808,7 @@
       ERROR(result, message.c_str());
     }
 
-    *tag_values_size = tag_size * entity_handles_size;
+    KEEP_ARRAY(tag_values);
     RETURN(iBase_SUCCESS);
   }
 
@@ -2137,8 +2094,7 @@
     CHKERR(result, "iMesh_getAllTags failed.");
     
       // now put those tag handles into sidl array
-    CHECK_SIZE(*tag_handles, *tag_handles_allocated,
-               (int)all_tags.size(), iBase_TagHandle, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY_NOFAIL(tag_handles, all_tags.size());
     memcpy(*tag_handles, &all_tags[0], all_tags.size()*sizeof(MBTag));
     *tag_handles_size = all_tags.size();
 
@@ -2379,8 +2335,7 @@
 
     int num_ents = out_entities.size();
     
-    CHECK_SIZE(*entity_handles, *entity_handles_allocated, 
-               num_ents, iBase_EntityHandle, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY_NOFAIL(entity_handles, num_ents);
   
     int k = 0;
 
@@ -2576,8 +2531,7 @@
 
     CHKERR(result,"iMesh_GetEntities:ERROR getting entities.");
 
-    CHECK_SIZE(*entity_handles, *entity_handles_allocated, 
-               (int)out_entities.size(), iBase_EntityHandle, iBase_MEMORY_ALLOCATION_FAILED);
+    ALLOC_CHECK_ARRAY_NOFAIL(entity_handles, out_entities.size());
   
     MBRange::iterator iter = out_entities.begin();
     MBRange::iterator end_iter = out_entities.end();
@@ -2622,14 +2576,9 @@
                                                MBInterface::INTERSECT, recursive);
     CHKERR(result,"ERROR getting entities.");
 
-    CHECK_SIZE(*set_handles, *set_handles_allocated, 
-               (int)out_entities.size(), iBase_EntitySetHandle, iBase_MEMORY_ALLOCATION_FAILED);
-
+    ALLOC_CHECK_ARRAY_NOFAIL(set_handles, out_entities.size());
+               
     std::copy(out_entities.begin(), out_entities.end(), ((MBEntityHandle*) *set_handles));
-  
-      // now it's safe to set the size; set it to k, not out_entities.size(), to
-      // account for sets which might have been removed
-    *set_handles_size = out_entities.size();
 
     RETURN(iBase_SUCCESS);
   }

Modified: MOAB/trunk/tools/iMesh/iMesh_MOAB.hpp
===================================================================
--- MOAB/trunk/tools/iMesh/iMesh_MOAB.hpp	2010-03-06 01:10:21 UTC (rev 3569)
+++ MOAB/trunk/tools/iMesh/iMesh_MOAB.hpp	2010-03-06 01:22:59 UTC (rev 3570)
@@ -4,6 +4,7 @@
 #include "iMesh.h"
 #include "MBForward.hpp"
 #include <cstring>
+#include <cstdlib>
 
 /* map from MB's entity type to TSTT's entity topology */
 extern const iMesh_EntityTopology tstt_topology_table[MBMAXTYPE+1];
@@ -96,4 +97,69 @@
   { return (MB_SUCCESS != code); }
 
 
+// Check the array size, and allocate the array if necessary.
+// Free the array upon leaving scope unless KEEP_ARRAY
+// is invoked.
+#define ALLOC_CHECK_ARRAY(array, this_size) \
+  iMeshArrayManager array ## _manager ( reinterpret_cast<void**>(array), *(array ## _allocated), *(array ## _size), this_size, sizeof(**array), err ); \
+  if (iBase_SUCCESS != *err) return
+
+#define ALLOC_CHECK_TAG_ARRAY(array, this_size) \
+  iMeshArrayManager array ## _manager ( reinterpret_cast<void**>(array), *(array ## _allocated), *(array ## _size), this_size, 1, err ); \
+  if (iBase_SUCCESS != *err) return
+
+#define KEEP_ARRAY(array) \
+  array ## _manager .keep_array()
+
+// Check the array size, and allocate the array if necessary.
+// Do NOT free the array upon leaving scope.
+#define ALLOC_CHECK_ARRAY_NOFAIL(array, this_size) \
+  ALLOC_CHECK_ARRAY(array, this_size); KEEP_ARRAY(array)
+
+
+// Implement RAII pattern for allocated arrays
+class iMeshArrayManager
+{
+  void** arrayPtr;
+
+public:
+
+
+  iMeshArrayManager( void** array_ptr,
+                     int& array_allocated_space,
+                     int& array_size,
+                     int count,
+                     int val_size,
+                     int* err ) : arrayPtr(0)
+  {
+    if (!*array_ptr) {
+      *array_ptr = std::malloc(val_size * count);
+      array_allocated_space = array_size = count;
+      if (!*array_ptr) {
+        IBASE_ERROR(iBase_MEMORY_ALLOCATION_FAILED, "Couldn't allocate array.");
+      }
+      arrayPtr = array_ptr;
+    }
+    else {
+      array_size = count;
+      if (array_allocated_space < count) {
+        IBASE_ERROR(iBase_BAD_ARRAY_DIMENSION, 
+          "Allocated array not large enough to hold returned contents.");
+      }
+    }
+    RETURN(iBase_SUCCESS);
+  }
+  
+  ~iMeshArrayManager() 
+  {
+    if (arrayPtr) {
+      std::free(*arrayPtr);
+      *arrayPtr = 0;
+    }
+  }
+  
+  void keep_array()
+    { arrayPtr = 0; }
+};
+
 #endif // IMESH_MOAB_HPP



More information about the moab-dev mailing list