[MOAB-dev] r1283 - MOAB/trunk

kraftche at mcs.anl.gov kraftche at mcs.anl.gov
Tue Sep 25 10:30:46 CDT 2007


Author: kraftche
Date: 2007-09-25 10:30:46 -0500 (Tue, 25 Sep 2007)
New Revision: 1283

Added:
   MOAB/trunk/README.RefCount
Modified:
   MOAB/trunk/AEntityFactory.cpp
   MOAB/trunk/AEntityFactory.hpp
   MOAB/trunk/EntitySequence.cpp
   MOAB/trunk/EntitySequence.hpp
   MOAB/trunk/EntitySequenceManager.hpp
   MOAB/trunk/HigherOrderFactory.cpp
   MOAB/trunk/MBCore.cpp
   MOAB/trunk/MBCore.hpp
   MOAB/trunk/MBMeshSet.cpp
   MOAB/trunk/MBMeshSet.hpp
   MOAB/trunk/MBReadUtil.cpp
   MOAB/trunk/MBReadUtil.hpp
   MOAB/trunk/MBReadUtilIface.hpp
   MOAB/trunk/MBTest.cpp
   MOAB/trunk/MeshSetSequence.cpp
   MOAB/trunk/MeshSetSequence.hpp
   MOAB/trunk/PolyEntitySequence.cpp
   MOAB/trunk/ReadGmsh.cpp
   MOAB/trunk/ReadHDF5.cpp
   MOAB/trunk/ReadNCDF.cpp
   MOAB/trunk/ReadSTL.cpp
   MOAB/trunk/ReadVtk.cpp
   MOAB/trunk/TagServer.cpp
   MOAB/trunk/TagServer.hpp
   MOAB/trunk/configure.in
Log:
Reference counting

Modified: MOAB/trunk/AEntityFactory.cpp
===================================================================
--- MOAB/trunk/AEntityFactory.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/AEntityFactory.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -17,7 +17,7 @@
 
 #include "AEntityFactory.hpp"
 #include "MBInternals.hpp"
-#include "MBInterface.hpp"
+#include "MBCore.hpp"
 #include "MBRange.hpp"
 #include "MBError.hpp"
 #include "MBCN.hpp"
@@ -27,9 +27,51 @@
 #include <algorithm>
 #include <set>
 
+#ifdef MOAB_WITH_REFCOUNT
+MBErrorCode AEntityFactory::decrement_reference_count( const MBEntityHandle* arr, size_t len )
+  { return thisMB->decrement_reference_count( arr, len ); }
+MBErrorCode AEntityFactory::increment_reference_count( const MBEntityHandle* arr, size_t len )
+  { return thisMB->increment_reference_count( arr, len ); }
+MBErrorCode AEntityFactory::decrement_referenced_entities( MBEntityHandle h )
+{
+  const MBEntityHandle* adj;
+  int num_adj;
+  MBErrorCode rval = get_adjacencies( h, adj, num_adj );
+  if (MB_SUCCESS != rval || num_adj == 0)
+    return rval;
+  
+  MBEntityType type = TYPE_FROM_HANDLE(h);
+  if (type == MBVERTEX)
+    return MB_SUCCESS;
+  --type;
+    
+  int junk;
+  const MBEntityHandle* end 
+    = std::lower_bound( adj, adj+num_adj, CREATE_HANDLE( type, 0, junk ) );
+  return decrement_reference_count( adj, end - adj );
+}
+MBErrorCode AEntityFactory::increment_referenced_entities( MBEntityHandle h )
+{
+  const MBEntityHandle* adj;
+  int num_adj;
+  MBErrorCode rval = get_adjacencies( h, adj, num_adj );
+  if (MB_SUCCESS != rval || num_adj == 0)
+    return rval;
+  
+  MBEntityType type = TYPE_FROM_HANDLE(h);
+  if (type == MBVERTEX)
+    return MB_SUCCESS;
+  --type;
+    
+  int junk;
+  const MBEntityHandle* end 
+    = std::lower_bound( adj, adj+num_adj, CREATE_HANDLE( type, 0, junk ) );
+  return increment_reference_count( adj, end - adj );
+}
+#endif
 
 
-AEntityFactory::AEntityFactory(MBInterface *mdb) 
+AEntityFactory::AEntityFactory(MBCore *mdb) 
 : mDensePageGroup(sizeof(void*), 0)
 {
   assert(NULL != mdb);
@@ -385,10 +427,10 @@
       // need to make a new adjacency list first
     adj_list_ptr = new MBAdjacencyVector();
     result = mDensePageGroup.set_data(from_ent, &adj_list_ptr);
-
+ 
     if (MB_SUCCESS != result) return result;
   }
-
+  
     // get an iterator to the right spot in this sorted vector
   MBAdjacencyVector::iterator adj_iter;
   if (!adj_list_ptr->empty()) 
@@ -399,10 +441,19 @@
     if ( adj_iter == adj_list_ptr->end() || to_ent != *adj_iter )
     {
       adj_list_ptr->insert(adj_iter, to_ent);
+#ifdef MOAB_WITH_REFCOUNT
+      if (TYPE_FROM_HANDLE(from_ent) > TYPE_FROM_HANDLE(to_ent))
+        increment_reference_count( to_ent );
+#endif
     }
   }
-  else
+  else {
     adj_list_ptr->push_back(to_ent);
+#ifdef MOAB_WITH_REFCOUNT
+    if (TYPE_FROM_HANDLE(from_ent) > TYPE_FROM_HANDLE(to_ent))
+      increment_reference_count( to_ent );
+#endif
+  }
 
     // if both_ways is true, recursively call this function
   if (true == both_ways && to_type != MBVERTEX)
@@ -413,7 +464,8 @@
 
 //! remove an adjacency from from the base_entity.
 MBErrorCode AEntityFactory::remove_adjacency(MBEntityHandle base_entity,
-                              MBEntityHandle adj_to_remove)
+                              MBEntityHandle adj_to_remove,
+                              bool update_reference_count)
 {
   MBErrorCode result;
 
@@ -435,20 +487,30 @@
 
   // remove the specified entity from the adjacency list and truncate
   // the list to the new length
-  adj_list->erase(std::remove(adj_list->begin(), adj_list->end(), adj_to_remove), 
-                  adj_list->end());
+  std::vector<MBEntityHandle>::iterator iter 
+    = std::lower_bound( adj_list->begin(), adj_list->end(), adj_to_remove );
+  if (iter == adj_list->end() || *iter != adj_to_remove)
+    return MB_FAILURE;
   
+  adj_list->erase( iter );
+#ifdef MOAB_WITH_REFCOUNT
+  if (update_reference_count && 
+      TYPE_FROM_HANDLE(base_entity) > TYPE_FROM_HANDLE(adj_to_remove))
+    decrement_reference_count( adj_to_remove );
+#endif
+  
   // reset the adjacency data list
   //result = thisMB->tag_set_data(adj_tag, base_entity, &adj_list);
   //if (result != MB_SUCCESS)
     //return result;
 
-  return result;
+  return MB_SUCCESS;
 }
 
 //! remove all adjacencies from from the base_entity.
 MBErrorCode AEntityFactory::remove_all_adjacencies(MBEntityHandle base_entity,
-                                                   const bool delete_adj_list)
+                                                   const bool delete_adj_list,
+                                                   bool update_reference_counts)
 {
   MBErrorCode result;
 
@@ -462,7 +524,7 @@
     if (MB_SUCCESS != result && MB_MULTIPLE_ENTITIES_FOUND != result) continue;
     for (MBRange::iterator rit = ents.begin(); rit != ents.end(); rit++) {
       if (explicitly_adjacent(*rit, base_entity))
-        remove_adjacency(*rit, base_entity);
+        remove_adjacency(*rit, base_entity, update_reference_counts);
     }
   }
   

Modified: MOAB/trunk/AEntityFactory.hpp
===================================================================
--- MOAB/trunk/AEntityFactory.hpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/AEntityFactory.hpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -26,13 +26,15 @@
 
 typedef std::vector<MBEntityHandle> MBAdjacencyVector;
 
+class MBCore;
+
 //! class AEntityFactory
 class AEntityFactory 
 {
 public:
 
   //! require an MBInterface object in order to access tags on that interface
-  AEntityFactory(MBInterface *mdb);
+  AEntityFactory(MBCore *mdb);
 
   //! destructor
   ~AEntityFactory();
@@ -47,11 +49,13 @@
 
 //! remove an adjacency from from the base_entity.
   MBErrorCode remove_adjacency(MBEntityHandle base_entity,
-                                MBEntityHandle adjacency_to_remove);
+                                MBEntityHandle adjacency_to_remove,
+                                bool update_reference_count = true);
 
 //! remove all adjacencies from from the base_entity.
   MBErrorCode remove_all_adjacencies(MBEntityHandle base_entity,
-                                     const bool delete_adj_list = false);
+                                     const bool delete_adj_list = false,
+                                     bool update_reference_counts = true);
   
 //! get the elements contained by source_entity, of
 //! type target_type, passing back in target_entities; if create_if_missing
@@ -140,13 +144,23 @@
                               unsigned long& total_entity_storage,
                               unsigned long& total_amortized_storage );
   
+#ifdef MOAB_WITH_REFCOUNT
+  MBErrorCode decrement_reference_count( const MBEntityHandle* arr, size_t len );
+  MBErrorCode increment_reference_count( const MBEntityHandle* arr, size_t len );
+  MBErrorCode decrement_reference_count( MBEntityHandle ent )
+    { return decrement_reference_count( &ent, 1 ); }
+  MBErrorCode increment_reference_count( MBEntityHandle ent )
+    { return increment_reference_count( &ent, 1 ); }
+  MBErrorCode decrement_referenced_entities( MBEntityHandle h );
+  MBErrorCode increment_referenced_entities( MBEntityHandle h );
+#endif
 private:
 
   //! private constructor to prevent the construction of a default one
   AEntityFactory();
 
   //! interface associated with this tool
-  MBInterface *thisMB;
+  MBCore *thisMB;
 
   //! adjacencies collection
   DensePageGroup mDensePageGroup;
@@ -203,7 +217,7 @@
 inline MBErrorCode AEntityFactory::notify_delete_entity(MBEntityHandle entity)
 {
   // remove any references to this entity from other entities
-  return remove_all_adjacencies(entity, true);
+  return remove_all_adjacencies(entity, true, false);
 }
 
 

Modified: MOAB/trunk/EntitySequence.cpp
===================================================================
--- MOAB/trunk/EntitySequence.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/EntitySequence.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -37,6 +37,9 @@
 MBEntitySequence::MBEntitySequence(EntitySequenceManager* seq_manager,
   MBEntityHandle start_handle, MBEntityID num_entities )
   : mSequenceManager(seq_manager)
+#ifdef MOAB_WTIH_REFCOUNT
+  , mRefCount( num_entities, 0 )
+#endif
 {
   assert(MB_START_ID <= ID_FROM_HANDLE(start_handle));
   assert(TYPE_FROM_HANDLE(start_handle) < MBMAXTYPE);
@@ -75,7 +78,13 @@
   mCoords[1] = new double[num_entities];
   mCoords[2] = new double[num_entities];
   
+#ifdef MOAB_WITH_REFCOUNT
+  mRefCount.clear();
+  mRefCount.resize( num_entities, all_handles_used ? 1 : 0 );
+#else
   mFreeEntities.clear();
+#endif
+
   if(all_handles_used)
   {
     mNumEntities = num_entities;
@@ -84,7 +93,9 @@
   else
   {
     seq_manager->notify_not_full(this);
+#ifndef MOAB_WITH_REFCOUNT
     mFreeEntities.resize(mNumAllocated, true);
+#endif
     mNumEntities = 0;
     mFirstFreeIndex = 0;
     for(MBEntityID i=0; i<num_entities; i++)
@@ -111,7 +122,11 @@
     return 0;
 
   MBEntityHandle new_handle = mStartEntityHandle + mFirstFreeIndex;
+#ifdef MOAB_WITH_REFCOUNT
+  mRefCount[mFirstFreeIndex] = 1;
+#else
   mFreeEntities[mFirstFreeIndex] = false;
+#endif
 
   mFirstFreeIndex = reinterpret_cast<MBEntityID&>(mCoords[0][mFirstFreeIndex]);
 
@@ -119,8 +134,10 @@
 
   if(mNumEntities == mNumAllocated) {
     mSequenceManager->notify_full(this);
+#ifndef MOAB_WITH_REFCOUNT
     std::vector<bool> empty;
     mFreeEntities.swap(empty);
+#endif
   }
 
   if( mLastDeletedIndex == (MBEntityID)( new_handle - mStartEntityHandle ))
@@ -135,12 +152,21 @@
   if(!is_valid_entity(handle))
     return;
 
+#ifdef MOAB_WITH_REFCOUNT
+  if (get_reference_count(handle) != 1) // only referenced by this sequence
+    return;
+  decrement_reference_count(handle);
+#endif
+
   if(mNumEntities == mNumAllocated) {
     mSequenceManager->notify_not_full(this);
+#ifndef MOAB_WITH_REFCOUNT
     mFreeEntities.resize( mNumAllocated, false );
+#endif
   }
-
+#ifndef MOAB_WITH_REFCOUNT
   mFreeEntities[handle - mStartEntityHandle] = true;
+#endif
 
   MBEntityID prev_free_handle = -1;
   const MBEntityID handle_index = handle - mStartEntityHandle;
@@ -206,13 +232,22 @@
                                            unsigned long& allocated) const
 {
   unsigned long per_ent = get_memory_use((MBEntityHandle)0);
-  allocated = sizeof(*this) + mFreeEntities.capacity()/8 + per_ent*number_allocated();
+  allocated = sizeof(*this) + per_ent*number_allocated();
+#ifdef MOAB_WITH_REFCOUNT
+  allocated += mRefCount.capacity() * sizeof(int);
+#else
+  allocated += mFreeEntities.capacity()/8;
+#endif
   used = per_ent * number_entities();
 }
 
 unsigned long VertexEntitySequence::get_memory_use( MBEntityHandle ) const
 {
+#ifdef MOAB_WITH_REFCOUNT
+  return 3 * sizeof(double) + sizeof(unsigned);
+#else
   return 3 * sizeof(double);
+#endif
 }
 
 MBEntityID ElementEntitySequence::get_next_free_index( MBEntityID prev_free_index ) const
@@ -246,7 +281,13 @@
 
   seq_manager->entity_sequence_created(this);
 
+#ifdef MOAB_WITH_REFCOUNT
+    mRefCount.clear();
+    mRefCount.resize( num_entities, all_handles_used ? 1 : 0 );
+#else
   mFreeEntities.clear();
+#endif
+
   if(all_handles_used)
   {
     mNumEntities = num_entities;
@@ -255,7 +296,9 @@
   else
   {
     seq_manager->notify_not_full(this);
+#ifndef MOAB_WITH_REFCOUNT
     mFreeEntities.resize( mNumAllocated, true );
+#endif
     mNumEntities = 0;
     mFirstFreeIndex = 0;
     if (nodes_per_element)
@@ -283,7 +326,11 @@
   if(mFirstFreeIndex == -1)
     return 0;
 
+#ifdef MOAB_WITH_REFCOUNT
+  mRefCount[mFirstFreeIndex] = 1;
+#else
   mFreeEntities[mFirstFreeIndex] = false;
+#endif
   MBEntityHandle new_handle = mStartEntityHandle + mFirstFreeIndex;
 
   mFirstFreeIndex = reinterpret_cast<MBEntityID&>(mElements[mFirstFreeIndex*mNodesPerElement]);
@@ -293,7 +340,9 @@
   if(mNumEntities == mNumAllocated) {
     mSequenceManager->notify_full(this);
     std::vector<bool> empty;
+#ifndef MOAB_WITH_REFCOUNT
     mFreeEntities.swap(empty);
+#endif
   }
   
   if( mLastDeletedIndex == (MBEntityID)( new_handle - mStartEntityHandle ))
@@ -307,12 +356,22 @@
   if(!is_valid_entity(handle))
     return;
 
+#ifdef MOAB_WITH_REFCOUNT
+  if (get_reference_count(handle) != 1)
+    return;
+  decrement_reference_count(handle);
+#endif
+
   if(mNumEntities == mNumAllocated) {
     mSequenceManager->notify_not_full(this);
+#ifndef MOAB_WITH_REFCOUNT
     mFreeEntities.resize( mNumAllocated, false );
+#endif
   }
 
+#ifndef MOAB_WITH_REFCOUNT
   mFreeEntities[handle-mStartEntityHandle] = true;
+#endif
   
   MBEntityID prev_free_index = -1;
   const MBEntityID handle_index = handle - mStartEntityHandle;
@@ -379,7 +438,7 @@
   assert(get_end_handle() >= split_location);
 
   // make a new sequence
-  const bool all_used = mFreeEntities.empty();
+  const bool all_used = (mNumEntities == mNumAllocated);
   ElementEntitySequence* seq = new ElementEntitySequence( mSequenceManager, split_location, 
       get_end_handle() - split_location + 1 , mNodesPerElement, all_used);
   new_sequence = seq;
@@ -405,6 +464,15 @@
     assert( seq->mNumEntities == seq->mNumAllocated );
     return MB_SUCCESS;
   }
+  
+#ifdef MOAB_WITH_REFCOUNT
+  const MBEntityHandle count = split_location - get_start_handle();
+  seq->mRefCount = mRefCount;
+  mRefCount.resize( count );
+  seq->mRefCount.erase( seq->mRefCount.begin(), seq->mRefCount.begin() + count );
+  std::vector<unsigned>(mRefCount).swap(mRefCount);
+  std::vector<unsigned>(seq->mRefCount).swap(seq->mRefCount);
+#else
 
   //copy free handles over too
   std::copy(mFreeEntities.begin()+(split_location-mStartEntityHandle),
@@ -413,21 +481,26 @@
   // shrink capacity to what we need
   mFreeEntities.resize(mNumAllocated);
   std::vector<bool>(mFreeEntities).swap(mFreeEntities);
+#endif
 
-
   // need to recompute : mNumEntities, mFirstFreeIndex for both sequences
   
   mNumEntities = 0;
   mFirstFreeIndex = -1;
   
+#ifdef MOAB_WITH_REFCOUNT
+  std::vector<unsigned>::reverse_iterator iter = mRefCount.rbegin();
+  std::vector<unsigned>::reverse_iterator end_iter = mRefCount.rend();
+#else
   std::vector<bool>::reverse_iterator iter = mFreeEntities.rbegin();
   std::vector<bool>::reverse_iterator end_iter = mFreeEntities.rend();
-  MBEntityID index = mFreeEntities.size() - 1;
+#endif
+  MBEntityID index = mNumAllocated - 1;
   MBEntityID last_index = -1;
 
   for(; iter != end_iter; )
   {
-    if(*iter == true)
+    if(*iter)
     {
       reinterpret_cast<MBEntityID&>(mElements[index*mNodesPerElement]) = last_index;
       last_index = index;
@@ -444,8 +517,10 @@
 
   if(mNumEntities == mNumAllocated) {
     mSequenceManager->notify_full(this);
+#ifndef MOAB_WITH_REFCOUNT
     std::vector<bool> empty;
     mFreeEntities.swap( empty );
+#endif
   }
   else
     mSequenceManager->notify_not_full(this);
@@ -454,14 +529,20 @@
   seq->mNumEntities = 0;
   seq->mFirstFreeIndex = -1;
   
+#ifdef MOAB_WITH_REFCOUNT
+  iter = seq->mRefCount.rbegin();
+  end_iter = seq->mRefCount.rend();
+  index = seq->mRefCount.size() - 1;
+#else
   iter = seq->mFreeEntities.rbegin();
   end_iter = seq->mFreeEntities.rend();
   index = seq->mFreeEntities.size() - 1;
+#endif
   last_index = -1;
 
   for(; iter != end_iter; )
   {
-    if(*iter == true)
+    if(*iter)
     {
       reinterpret_cast<MBEntityID&>(seq->mElements[index*mNodesPerElement]) = last_index;
       last_index = index;
@@ -478,8 +559,10 @@
   
   if(seq->mNumEntities == seq->mNumAllocated) {
     mSequenceManager->notify_full(seq);
+#ifndef MOAB_WITH_REFCOUNT
     std::vector<bool> empty;
     seq->mFreeEntities.swap( empty );
+#endif
   }
   else
     mSequenceManager->notify_not_full(seq);
@@ -490,10 +573,15 @@
 
 
 MBErrorCode ElementEntitySequence::convert_realloc(bool& mid_edge_nodes,
-    bool& mid_face_nodes, bool& mid_volume_nodes, MBCore* MB, 
-    MBTag delete_mark_bit )
+    bool& mid_face_nodes, bool& mid_volume_nodes, MBCore* MB
+#ifndef MOAB_WITH_REFCOUNT
+    , MBTag delete_mark_bit 
+#endif
+    )
 {
-
+#ifdef MOAB_WITH_REFCOUNT
+  MBRange dead_nodes;
+#endif
   MBEntityType this_type = get_type();
 
   // figure out how many nodes per element we'll end up with
@@ -546,13 +634,22 @@
     old_end_handle = mElements + mNodesPerElement*mNumAllocated;
     old_iter = mElements + MBCN::VerticesPerEntity(this_type);
 
+#ifndef MOAB_WITH_REFCOUNT
     std::set<MBEntityHandle> nodes_processed; 
+#endif
     for(; old_iter < old_end_handle; )
     {
       //tag each node-to-delete with parent element entity handle and number 
       //of elements it is found on
       for(int i=0; i<number_to_delete; i++)
       {
+#ifdef MOAB_WITH_REFCOUNT
+        if (old_iter[i]) {
+          MB->decrement_reference_count( old_iter[i] );
+          if (MB->get_reference_count( old_iter[i] ) == 1)
+            dead_nodes.insert( old_iter[i] );
+        }
+#else
         //see if node has been processed yet
         if( old_iter[i] && nodes_processed.insert(old_iter[i]).second )
         {
@@ -565,6 +662,7 @@
             MB->tag_set_data(delete_mark_bit, &(old_iter[i]), 1, &bit);
           }
         }
+#endif
       }
       old_iter += mNodesPerElement;
     }
@@ -598,13 +696,22 @@
     if(has_mid_edge_nodes())
       old_iter+=MBCN::mConnectivityMap[this_type][0].num_sub_elements;
 
+#ifndef MOAB_WITH_REFCOUNT
     std::set<MBEntityHandle> nodes_processed; 
+#endif
     for(; old_iter < old_end_handle; )
     {
       //tag each node-to-delete with parent element entity handle and number 
       //of elements it is found on
       for(int i=0; i<number_to_delete; i++)
       {
+#ifdef MOAB_WITH_REFCOUNT
+        if (old_iter[i]) {
+          MB->decrement_reference_count( old_iter[i] );
+          if (MB->get_reference_count( old_iter[i] ) == 1)
+            dead_nodes.insert( old_iter[i] );
+        }
+#else
         //see if node has been processed yet
         if( old_iter[i] && nodes_processed.insert(old_iter[i]).second )
         {
@@ -617,6 +724,7 @@
             MB->tag_set_data(delete_mark_bit, &(old_iter[i]), 1, &bit);
           }
         }
+#endif
       }
       old_iter += mNodesPerElement;
     }
@@ -653,12 +761,20 @@
    
     for(; old_iter < old_end_handle; )
     {
+#ifdef MOAB_WITH_REFCOUNT
+      if (*old_iter) {
+        MB->sequence_manager()->decrement_reference_count( *old_iter );
+        if (MB->get_reference_count( *old_iter ) == 1)
+          dead_nodes.insert( *old_iter );
+      }
+#else
       if( *old_iter != 0 && tag_for_deletion( old_iter - mElements, MB ) )
       {
         //tag node as deletable
         unsigned char bit = 0x1;
         MB->tag_set_data(delete_mark_bit, &(*old_iter), 1, &bit);
       }
+#endif
       old_iter += mNodesPerElement;
     }
 
@@ -677,8 +793,12 @@
   mElements = new_array;
 
   mNodesPerElement = new_nodes_per_element;
-  
+
+#ifdef MOAB_WITH_REFCOUNT
+  return MB->delete_entities( dead_nodes );
+#else  
   return MB_SUCCESS;
+#endif
 }
 
 bool ElementEntitySequence::has_mid_edge_nodes() const
@@ -797,11 +917,37 @@
                                             unsigned long& allocated) const
 {
   unsigned long per_ent = get_memory_use((MBEntityHandle)0);
-  allocated = sizeof(*this) + mFreeEntities.capacity()/8 + per_ent*number_allocated();
+  allocated = sizeof(*this) + per_ent*number_allocated();
+#ifdef MOAB_WITH_REFCOUNT
+  allocated += mRefCount.capacity() * sizeof(unsigned);
+#else
+  allocated += mFreeEntities.capacity()/8;
+#endif
   used = per_ent * number_entities();
 }
 
 unsigned long ElementEntitySequence::get_memory_use( MBEntityHandle ) const
 {
+#ifdef MOAB_WITH_REFCOUNT
+  return sizeof(MBEntityHandle) * nodes_per_element() + sizeof(unsigned);
+#else
   return sizeof(MBEntityHandle) * nodes_per_element();
+#endif
 }
+
+#ifdef MOAB_WITH_REFCOUNT
+void ElementEntitySequence::decrement_all_referenced_entities( MBEntityHandle entity, AEntityFactory* f)
+{
+  const MBEntityHandle* conn;
+  int len;
+  if (MB_SUCCESS == get_connectivity( entity, conn, len )) 
+    f->decrement_reference_count( conn, len );
+}  
+void ElementEntitySequence::increment_all_referenced_entities( MBEntityHandle entity, AEntityFactory* f)
+{
+  const MBEntityHandle* conn;
+  int len;
+  if (MB_SUCCESS == get_connectivity( entity, conn, len )) 
+    f->increment_reference_count( conn, len );
+}  
+#endif

Modified: MOAB/trunk/EntitySequence.hpp
===================================================================
--- MOAB/trunk/EntitySequence.hpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/EntitySequence.hpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -42,6 +42,7 @@
 
 class EntitySequenceManager;
 class MBCore;
+class AEntityFactory;
 
 class MBEntitySequence
 {
@@ -101,6 +102,18 @@
                                unsigned long& allocated ) const = 0;
   virtual unsigned long get_memory_use( MBEntityHandle handle ) const = 0;
 
+#ifdef MOAB_WITH_REFCOUNT
+  unsigned increment_reference_count( MBEntityHandle entity )
+    { return ++mRefCount[entity-get_start_handle()]; }
+  unsigned decrement_reference_count( MBEntityHandle entity )
+    { return --mRefCount[entity-get_start_handle()]; }
+  unsigned get_reference_count( MBEntityHandle entity) const
+    { return mRefCount[entity-get_start_handle()]; }
+  
+  virtual void decrement_all_referenced_entities( MBEntityHandle entity, AEntityFactory* ) = 0;
+  virtual void increment_all_referenced_entities( MBEntityHandle entity, AEntityFactory* ) = 0;
+#endif
+
 protected:
 
   EntitySequenceManager* mSequenceManager;
@@ -122,8 +135,11 @@
   MBEntityID            mLastDeletedIndex;
 
   //! a list of whether entities are free or not
+#ifdef MOAB_WITH_REFCOUNT
+  std::vector<unsigned> mRefCount;
+#else
   std::vector<bool>     mFreeEntities;
-
+#endif
 };
 
 
@@ -162,6 +178,11 @@
 
   virtual void get_memory_use( unsigned long& used, unsigned long& allocated ) const;
   virtual unsigned long get_memory_use( MBEntityHandle handle ) const;
+
+#ifdef MOAB_WITH_REFCOUNT
+  virtual void decrement_all_referenced_entities( MBEntityHandle , AEntityFactory* ) {}
+  virtual void increment_all_referenced_entities( MBEntityHandle , AEntityFactory* ) {}
+#endif
 private:
 
   // coordinate arrays x,y,z
@@ -207,7 +228,11 @@
   // reallocated the sequence to hold extra/less nodes, pass in what you want, and will return whether it needed
   // reallocate space for those nodes
   virtual MBErrorCode convert_realloc(bool& mid_edge_nodes, bool& mid_face_nodes, bool& mid_volume_nodes, 
-      MBCore* MB, MBTag bit_delete_mark );
+      MBCore* MB
+#ifndef MOAB_WITH_REFCOUNT
+      , MBTag bit_delete_mark 
+#endif
+      );
   
   virtual bool has_mid_edge_nodes() const;
   virtual bool has_mid_face_nodes() const;
@@ -216,6 +241,10 @@
   virtual void get_memory_use( unsigned long& used, unsigned long& allocated ) const;
   virtual unsigned long get_memory_use( MBEntityHandle handle ) const;
 
+#ifdef MOAB_WITH_REFCOUNT
+  virtual void decrement_all_referenced_entities( MBEntityHandle entity, AEntityFactory* f);
+  virtual void increment_all_referenced_entities( MBEntityHandle entity, AEntityFactory* f);
+#endif
 protected:
   
   unsigned short mNodesPerElement;
@@ -232,7 +261,11 @@
 
 inline bool MBEntitySequence::is_valid_entity(MBEntityHandle entity) const
 {
+#ifdef MOAB_WITH_REFCOUNT
+  return 0 != get_reference_count(entity);
+#else
   return mFreeEntities.empty() || !mFreeEntities[entity-mStartEntityHandle];
+#endif
 }
 
 

Modified: MOAB/trunk/EntitySequenceManager.hpp
===================================================================
--- MOAB/trunk/EntitySequenceManager.hpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/EntitySequenceManager.hpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -43,9 +43,9 @@
 
 #include "MBForward.hpp"
 #include "MBProcConfig.hpp"
+#include "EntitySequence.hpp"
 #include <map>
 
-class MBEntitySequence;
 class HomCoord;
 
 //! class for managing entity sequences
@@ -137,6 +137,12 @@
                               unsigned long& total_entity_storage,
                               unsigned long& total_amortized_storage ) const;
 
+#ifdef MOAB_WITH_REFCOUNT
+  inline unsigned increment_reference_count( MBEntityHandle handle );
+  inline unsigned decrement_reference_count( MBEntityHandle handle );
+  inline unsigned get_reference_count( MBEntityHandle handle ) const;
+#endif
+
 private:
   
   //! creates an entity sequence with a start handle and number of entities
@@ -174,6 +180,24 @@
   const MBProcConfig procInfo;
 };
 
+#ifdef MOAB_WITH_REFCOUNT
+unsigned EntitySequenceManager::increment_reference_count( MBEntityHandle handle )
+{
+  MBEntitySequence* seq;
+  return MB_SUCCESS == find( handle, seq ) ? seq->increment_reference_count(handle) : 0;
+}
+unsigned EntitySequenceManager::decrement_reference_count( MBEntityHandle handle )
+{
+  MBEntitySequence* seq;
+  return MB_SUCCESS == find( handle, seq ) ? seq->decrement_reference_count(handle) : 0;
+}
+unsigned EntitySequenceManager::get_reference_count( MBEntityHandle handle ) const
+{
+  MBEntitySequence* seq;
+  return MB_SUCCESS == find( handle, seq ) ? seq->get_reference_count(handle) : 0;
+}
 #endif
 
+#endif
 
+

Modified: MOAB/trunk/HigherOrderFactory.cpp
===================================================================
--- MOAB/trunk/HigherOrderFactory.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/HigherOrderFactory.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -234,6 +234,10 @@
   if(this_type == MBTRI || this_type == MBQUAD)
     temp_mid_volume = false;
 
+#ifdef MOAB_WITH_REFCOUNT
+  seq->convert_realloc(temp_mid_edge, temp_mid_face, temp_mid_volume, mMB);
+
+#else
   MBTag deletable_nodes;
   mMB->tag_create("", 1, MB_TAG_BIT, deletable_nodes, NULL);
 
@@ -262,6 +266,7 @@
   }
   
   mMB->tag_delete(deletable_nodes);
+#endif
 
   // create mid edge nodes if necessary
   if(temp_mid_edge)
@@ -327,6 +332,9 @@
 
     // create a new vertex at the centroid
     mMB->create_vertex(sum_coords, element[new_node_index]);
+#ifdef MOAB_WITH_REFCOUNT
+    mMB->increment_reference_count( element[new_node_index] );
+#endif
     
     if(mHONodeAddedRemoved)
       mHONodeAddedRemoved->node_added(element[new_node_index], curr_handle);
@@ -413,6 +421,9 @@
 
         mMB->create_vertex(sum_coords, element[i+num_edges+num_vertices]);
       }
+#ifdef MOAB_WITH_REFCOUNT
+      mMB->increment_reference_count( element[i+num_edges+num_vertices] );
+#endif
 
       if(mHONodeAddedRemoved)
         mHONodeAddedRemoved->node_added(element[i+num_edges+num_vertices], curr_handle);
@@ -498,6 +509,9 @@
 
         mMB->create_vertex(sum_coords, element[i+num_vertices]);
       }
+#ifdef MOAB_WITH_REFCOUNT
+      mMB->increment_reference_count( element[i+num_vertices] );
+#endif
 
       if(mHONodeAddedRemoved)
         mHONodeAddedRemoved->node_added(element[i+num_vertices], curr_handle);

Modified: MOAB/trunk/MBCore.cpp
===================================================================
--- MOAB/trunk/MBCore.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/MBCore.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -950,13 +950,23 @@
 
   aEntityFactory->notify_change_connectivity(
     entity_handle, old_conn, connect, num_connect);
+#ifdef MOAB_WITH_REFCOUNT
+  decrement_reference_count( old_conn, num_connect );
+#endif
   
   status = static_cast<ElementEntitySequence*>(seq)->set_connectivity(entity_handle, 
                                                                       connect, num_connect);
-  if (status != MB_SUCCESS) 
+  if (status != MB_SUCCESS) {
     aEntityFactory->notify_change_connectivity(
       entity_handle, connect, old_conn, num_connect);
-
+#ifdef MOAB_WITH_REFCOUNT
+    increment_reference_count( old_conn, num_connect );
+  }
+  else {
+    increment_reference_count( connect, num_connect );
+#endif
+  }
+  
   return status;
 }
 
@@ -1387,22 +1397,86 @@
                                     const int num_entities,
                                     const void *tag_data)
 {
-  if (NULL == entity_handles && 0 == num_entities)
-    return tagServer->set_mesh_data(tag_handle, tag_data);
+  MBErrorCode rval;
+#ifdef MOAB_WITH_REFCOUNT
+  std::vector<MBEntityHandle> old_data;
+  std::vector<MBEntityHandle> unique_handles;
+  const TagInfo* tag_info = tagServer->get_tag_info( tag_handle );
+  if(!tag_info)
+    return MB_TAG_NOT_FOUND;
+  int count;
+#endif
 
+  if (NULL == entity_handles && 0 == num_entities) {
+#ifdef MOAB_WITH_REFCOUNT   
+    if (tag_info->get_data_type() == MB_TYPE_HANDLE) {
+      count = tag_info->get_size() / sizeof(MBEntityHandle);
+      old_data.resize( count );
+      rval = tagServer->get_mesh_data( tag_handle, &old_data[0] );
+      if (MB_SUCCESS == rval) {
+        rval = decrement_reference_count( &old_data[0], count );
+        if (MB_SUCCESS != rval)
+          return rval;
+      }
+      else 
+        old_data.clear();
+    }
+#endif  
+    rval = tagServer->set_mesh_data(tag_handle, tag_data);
+  }
+  else {
   //verify handles
-  MBEntitySequence* seq;
-  const MBEntityHandle* iter;
-  const MBEntityHandle* end = entity_handles + num_entities;
-  for(iter = entity_handles; iter != end; ++iter)
-  {
-    if (TYPE_FROM_HANDLE(*iter) == MBENTITYSET) continue;
+    MBEntitySequence* seq;
+    const MBEntityHandle* iter;
+    const MBEntityHandle* end = entity_handles + num_entities;
+    for(iter = entity_handles; iter != end; ++iter)
+    {
+      if (TYPE_FROM_HANDLE(*iter) == MBENTITYSET) continue;
+
+      else if(sequenceManager->find(*iter, seq) != MB_SUCCESS)
+        return MB_ENTITY_NOT_FOUND;
+    }
     
-    else if(sequenceManager->find(*iter, seq) != MB_SUCCESS)
-      return MB_ENTITY_NOT_FOUND;
+#ifdef MOAB_WITH_REFCOUNT   
+    if (tag_info->get_data_type() == MB_TYPE_HANDLE) {
+      unique_handles.resize( num_entities );
+      std::copy( entity_handles, entity_handles+num_entities, unique_handles.begin() );
+      std::sort( unique_handles.begin(), unique_handles.end() );
+      unique_handles.erase( std::unique( unique_handles.begin(), unique_handles.end() ), unique_handles.end() );
+      
+      count = tag_info->get_size() * unique_handles.size() / sizeof(MBEntityHandle);
+      old_data.resize( count );
+      rval = tagServer->get_mesh_data( tag_handle, &old_data[0] );
+      if (MB_SUCCESS == rval) {
+        rval = decrement_reference_count( &old_data[0], count );
+        if (MB_SUCCESS != rval)
+          return rval;
+      }
+      else 
+        old_data.clear();
+    }
+#endif
+
+    rval = tagServer->set_data(tag_handle, entity_handles, num_entities, tag_data);
   }
 
-  return tagServer->set_data(tag_handle, entity_handles, num_entities, tag_data);
+#ifdef MOAB_WITH_REFCOUNT
+  if (tag_info->get_data_type() == MB_TYPE_HANDLE) {
+    if (MB_SUCCESS == rval) {
+      if (unique_handles.size()) {
+        tag_server()->get_data( tag_handle, &unique_handles[0], unique_handles.size(), &old_data[0] );
+        rval = increment_reference_count( &old_data[0], count );
+      }
+      else {
+        rval = increment_reference_count( (const MBEntityHandle*)tag_data, count );
+      }
+    }
+    else if (!old_data.empty())
+      increment_reference_count( &old_data[0], count );  
+  }
+#endif
+
+  return rval;
 }
 
 //! set the data  for given EntityHandles and MBTag
@@ -1423,7 +1497,39 @@
       return result;
   }
 
-  return tagServer->set_data(tag_handle, entity_handles, tag_data);
+#ifdef MOAB_WITH_REFCOUNT
+  std::vector<MBEntityHandle> old_data;
+  const TagInfo* tag_info = tagServer->get_tag_info( tag_handle );
+  if(!tag_info)
+    return MB_TAG_NOT_FOUND;
+  int count;
+  if (tag_info->get_data_type() == MB_TYPE_HANDLE) {
+    count = tag_info->get_size() * entity_handles.size() / sizeof(MBEntityHandle);
+    old_data.resize( count );
+    result = tagServer->get_data( tag_handle, entity_handles, &old_data[0] );
+    if (MB_SUCCESS != result)
+      old_data.clear();
+    else {
+      result = decrement_reference_count( &old_data[0], count );
+      if (MB_SUCCESS != result)
+        return result;
+    }
+  }
+#endif
+
+  result = tagServer->set_data(tag_handle, entity_handles, tag_data);
+
+#ifdef MOAB_WITH_REFCOUNT
+  if (tag_info->get_data_type() == MB_TYPE_HANDLE) {
+    if (MB_SUCCESS == result) 
+      result = increment_reference_count( (const MBEntityHandle*)tag_data, count );
+    else if (!old_data.empty())
+      increment_reference_count( &old_data[0], count );  
+  }
+#endif
+
+  return result;
+
 }
 
 //! adds a sparse tag for this specific EntityHandle/tag_name combination
@@ -1445,6 +1551,17 @@
                                 const void* def_val,
                                 bool use_existing )
 {
+#ifdef MOAB_WITH_REFCOUNT
+    // don't allow a non-zero default value for handle-type tags
+    // if reference counting is enabled.
+  if (data == MB_TYPE_HANDLE && def_val) {
+    const MBEntityHandle* handles = (const MBEntityHandle*)def_val;
+    for (size_t i = 0; i < size / sizeof(MBEntityHandle); ++i)
+      if (handles[i])
+        return MB_FAILURE;
+  }
+#endif
+
   MBErrorCode rval = tagServer->add_tag( name, size, storage, data, handle, def_val );
 
     // If it is okay to use an existing tag of the same name, check that it 
@@ -1484,11 +1601,32 @@
     return MB_FAILURE;
 
   MBErrorCode status = MB_SUCCESS, temp_status;
+#ifdef MOAB_WITH_REFCOUNT
+  std::vector<MBEntityHandle> old_data;
+  const TagInfo* tag_info = tagServer->get_tag_info( tag_handle );
+  if(!tag_info)
+    return MB_TAG_NOT_FOUND;
+  if (tag_info->get_data_type() == MB_TYPE_HANDLE)
+    old_data.resize( tag_info->get_size()/sizeof(MBEntityHandle) );
+#endif
+
   for (int i = 0; i < num_handles; i++) {
-    if (0 == entity_handles[i])
+    if (0 == entity_handles[i]) {
+#ifdef MOAB_WITH_REFCOUNT
+      if (tag_info->get_data_type() == MB_TYPE_HANDLE &&
+          MB_SUCCESS == tagServer->get_mesh_data( tag_handle, &old_data[0] ))
+        decrement_reference_count( &old_data[0], old_data.size() );
+#endif
       temp_status = tagServer->remove_mesh_data(tag_handle);
-    else
+    }
+    else {
+#ifdef MOAB_WITH_REFCOUNT
+      if (tag_info->get_data_type() == MB_TYPE_HANDLE &&
+          MB_SUCCESS == tagServer->get_data( tag_handle, entity_handles+i, 1, &old_data[0] ))
+        decrement_reference_count( &old_data[0], old_data.size() );
+#endif
       temp_status = tagServer->remove_data(tag_handle, entity_handles[i]);
+    }
     if (temp_status != MB_SUCCESS) status = temp_status;
   }
 
@@ -1502,8 +1640,22 @@
   if (PROP_FROM_TAG_HANDLE(tag_handle) == MB_TAG_DENSE)
     return MB_FAILURE;
 
+#ifdef MOAB_WITH_REFCOUNT
+  std::vector<MBEntityHandle> old_data;
+  const TagInfo* tag_info = tagServer->get_tag_info( tag_handle );
+  if(!tag_info)
+    return MB_TAG_NOT_FOUND;
+  if (tag_info->get_data_type() == MB_TYPE_HANDLE)
+    old_data.resize( tag_info->get_size()/sizeof(MBEntityHandle) );
+#endif
+
   MBErrorCode status = MB_SUCCESS, temp_status;
   for (MBRange::const_iterator it = entity_handles.begin(); it != entity_handles.end(); it++) {
+#ifdef MOAB_WITH_REFCOUNT
+    if (tag_info->get_data_type() == MB_TYPE_HANDLE &&
+        MB_SUCCESS == tagServer->get_data( tag_handle, &*it, 1, &old_data[0] ))
+      decrement_reference_count( &old_data[0], old_data.size() );
+#endif
     temp_status = tagServer->remove_data(tag_handle, *it);
     if (temp_status != MB_SUCCESS) status = temp_status;
   }
@@ -1514,6 +1666,21 @@
 //! removes the tag from MB
 MBErrorCode  MBCore::tag_delete(MBTag tag_handle)
 {
+#ifdef MOAB_WITH_REFCOUNT
+  const TagInfo* tag_info = tagServer->get_tag_info( tag_handle );
+  if(!tag_info)
+    return MB_TAG_NOT_FOUND;
+  if (tag_info->get_data_type() == MB_TYPE_HANDLE) {
+    std::vector<MBEntityHandle> tag_data;
+    for (MBEntityType t = MBVERTEX; t <= MBENTITYSET; ++t) {
+      MBRange entities;
+      tagServer->get_entities( tag_handle, t, entities );
+      tag_data.resize( entities.size() );
+      tagServer->get_data( tag_handle, entities, &tag_data[0] );
+      decrement_reference_count( &tag_data[0], tag_data.size() );
+    }
+  }
+#endif
   return tag_server()->remove_tag(tag_handle);
 }
 
@@ -1749,50 +1916,82 @@
 }
 
 
+MBErrorCode MBCore::delete_entity( MBEntityHandle handle )
+{
+  MBErrorCode result;
+
+    // tell AEntityFactory that this element is going away
+  result = aEntityFactory->notify_delete_entity(handle);
+  if (MB_SUCCESS != result) 
+    return result;
+
+    // reset and/or clean out data associated with this entity handle
+  result = tagServer->reset_data(handle);
+  if (MB_SUCCESS != result) 
+    return result;
+
+  if (TYPE_FROM_HANDLE(handle) == MBENTITYSET) {
+    if (MBMeshSet* ptr = get_mesh_set( sequence_manager(), handle )) {
+      int j, count;
+      const MBEntityHandle* rel;
+      ptr->clear( handle, a_entity_factory() );
+      rel = ptr->get_parents( count );
+      for (j = 0; j < count; ++j)
+        remove_child_meshset( rel[j], handle );
+      rel = ptr->get_children( count );
+      for (j = 0; j < count; ++j)
+        remove_parent_meshset( rel[j],handle );
+    }
+  }
+
+    // now delete the entity
+  result = sequence_manager()->delete_entity(handle);
+  if (MB_SUCCESS != result) 
+    return result;
+  
+  return MB_SUCCESS;
+}
+
 //! deletes an entity vector
 MBErrorCode MBCore::delete_entities(const MBEntityHandle *entities,
                                       const int num_entities)
 {
+  // If reference counting is enabled, make sure all entities 
+  // are unreferenced, assuming all other entities in the list
+  // are also deleted.
+#ifdef MOAB_WITH_REFCOUNT
+  std::vector<MBTag> handle_tags;
+  tag_server()->get_tags( MB_TYPE_HANDLE, handle_tags );
+  
+  int ii, jj;
+    // before deleting each entity, decrement the reference count on
+    // everything that entity references.
+  for (ii = 0; ii < num_entities; ++ii) 
+    if (MB_SUCCESS != decrement_all_referenced_entities( entities[ii], handle_tags )) 
+      break;
+    // make sure everything that is to be deleted has a reference count 
+    // of 1 (only referenced by the containing sequence).
+  if (ii == num_entities) 
+    for (jj = 0; jj < num_entities; ++jj) 
+      if (get_reference_count( entities[jj] ) != 1)
+        break;
+    // if we can't delete the entities, but the reference counts back
+    // to what they were before and return failure.
+  if (ii < num_entities || jj < num_entities) {
+    while (ii > 0)
+      increment_all_referenced_entities( entities[--ii], handle_tags );
+    return MB_FAILURE;
+  }
+  
+#endif  
+
   MBErrorCode result = MB_SUCCESS, temp_result;
-  
   for (int i = 0; i < num_entities; i++) {
-    
-      // tell AEntityFactory that this element is going away
-    temp_result = aEntityFactory->notify_delete_entity(entities[i]);
-    if (MB_SUCCESS != temp_result) {
+    temp_result = delete_entity( entities[i] );
+    if (MB_SUCCESS != temp_result)
       result = temp_result;
-      continue;
-    }
-
-      // reset and/or clean out data associated with this entity handle
-    temp_result = tagServer->reset_data(entities[i]);
-    if (MB_SUCCESS != temp_result) {
-      result = temp_result;
-      continue;
-    }
-
-    if (TYPE_FROM_HANDLE(entities[i]) == MBENTITYSET) {
-      if (MBMeshSet* ptr = get_mesh_set( sequence_manager(), entities[i] )) {
-        int j, count;
-        const MBEntityHandle* rel;
-        ptr->clear( entities[i], a_entity_factory() );
-        rel = ptr->get_parents( count );
-        for (j = 0; j < count; ++j)
-          remove_child_meshset( rel[j], entities[i] );
-        rel = ptr->get_children( count );
-        for (j = 0; j < count; ++j)
-          remove_parent_meshset( rel[j], entities[i] );
-      }
-    }
-
-      // now delete the entity
-    temp_result = sequence_manager()->delete_entity(entities[i]);
-    if (MB_SUCCESS != temp_result) {
-      result = temp_result;
-      continue;
-    }
   }
-
+    
   return result;
 }
 
@@ -1800,9 +1999,36 @@
 //! deletes an entity range
 MBErrorCode MBCore::delete_entities(const MBRange &range)
 {
+  // If reference counting is enabled, make sure all entities 
+  // are unreferenced, assuming all other entities in the list
+  // are also deleted.
+#ifdef MOAB_WITH_REFCOUNT
+  std::vector<MBTag> handle_tags;
+  tag_server()->get_tags( MB_TYPE_HANDLE, handle_tags );
+  
+  MBRange::const_iterator ii, jj;
+    // before deleting each entity, decrement the reference count on
+    // everything that entity references.
+  for (ii = range.begin(); ii != range.end(); ++ii) 
+    if (MB_SUCCESS != decrement_all_referenced_entities( *ii, handle_tags )) 
+      break;
+    // make sure everything that is to be deleted has a reference count 
+    // of 1 (only referenced by the containing sequence).
+  if (ii == range.end()) 
+    for (jj = range.begin(); jj != range.end(); ++jj) 
+      if (get_reference_count( *jj ) != 1)
+        break;
+    // if we can't delete the entities, but the reference counts back
+    // to what they were before and return failure.
+  if (ii != range.end() || jj != range.end()) {
+    while (ii != range.begin())
+      increment_all_referenced_entities( *--ii, handle_tags );
+    return MB_FAILURE;
+  }
+#endif  
   MBErrorCode result = MB_SUCCESS, rval;
   for (MBRange::iterator i = range.begin(); i != range.end(); ++i)
-    if (MB_SUCCESS != (rval = delete_entities( &*i, 1)))
+    if (MB_SUCCESS != (rval = delete_entity( *i )))
       result = rval;
   return rval;
 }
@@ -2366,13 +2592,7 @@
 MBErrorCode MBCore::add_parent_meshset( MBEntityHandle meshset, 
                                         const MBEntityHandle parent_meshset)
 {
-  MBMeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
-  MBMeshSet* parent_ptr = get_mesh_set( sequence_manager(), parent_meshset );
-  if (!set_ptr || !parent_ptr)
-    return MB_ENTITY_NOT_FOUND;
-
-  set_ptr->add_parent( parent_meshset );
-  return MB_SUCCESS;
+  return add_parent_meshsets( meshset, &parent_meshset, 1 );
 }
 
 MBErrorCode MBCore::add_parent_meshsets( MBEntityHandle meshset, 
@@ -2387,21 +2607,21 @@
     if (!get_mesh_set( sequence_manager(), parents[i] ))
       return MB_ENTITY_NOT_FOUND;
     
+#ifdef MOAB_WITH_REFCOUNT
   for (int i = 0; i < count; ++i)
+    if (set_ptr->add_parent( parents[i] ))
+      increment_reference_count( parents + i, 1 );
+#else
+  for (int i = 0; i < count; ++i)
     set_ptr->add_parent( parents[i] );
+#endif
   return MB_SUCCESS;
 }
 
 MBErrorCode MBCore::add_child_meshset(MBEntityHandle meshset, 
                                         const MBEntityHandle child_meshset)
 {
-  MBMeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
-  MBMeshSet* child_ptr = get_mesh_set( sequence_manager(), child_meshset );
-  if (!set_ptr || !child_ptr)
-    return MB_ENTITY_NOT_FOUND;
-
-  set_ptr->add_child( child_meshset );
-  return MB_SUCCESS;
+  return add_child_meshsets( meshset, &child_meshset, 1 );
 }
 
 MBErrorCode MBCore::add_child_meshsets( MBEntityHandle meshset, 
@@ -2416,8 +2636,14 @@
     if (!get_mesh_set( sequence_manager(), children[i] ))
       return MB_ENTITY_NOT_FOUND;
     
+#ifdef MOAB_WITH_REFCOUNT
   for (int i = 0; i < count; ++i)
+    if (set_ptr->add_child( children[i] ))
+      increment_reference_count( children+i, 1 );
+#else
+  for (int i = 0; i < count; ++i)
     set_ptr->add_child( children[i] );
+#endif
   return MB_SUCCESS;
 }
 
@@ -2429,9 +2655,16 @@
   MBMeshSet* child_ptr = get_mesh_set( sequence_manager(), child );
   if (!parent_ptr || !child_ptr)
     return MB_ENTITY_NOT_FOUND;
-  
+
+#ifdef MOAB_WITH_REFCOUNT
+  if (parent_ptr->add_child( child ))
+    increment_reference_count( &child, 1 );
+  if (child_ptr->add_parent( parent ))
+    increment_reference_count( &parent, 1 );
+#else
   parent_ptr->add_child( child );
   child_ptr->add_parent( parent );
+#endif
   return MB_SUCCESS;
 }
 
@@ -2443,8 +2676,15 @@
   if (!parent_ptr || !child_ptr)
     return MB_ENTITY_NOT_FOUND;
   
+#ifdef MOAB_WITH_REFCOUNT
+  if (parent_ptr->remove_child( child ))
+    decrement_reference_count( &child, 1 );
+  if (child_ptr->remove_parent( parent ))
+    decrement_reference_count( &parent, 1 );
+#else
   parent_ptr->remove_child( child );
   child_ptr->remove_parent( parent );
+#endif
   return MB_SUCCESS;
 }
 
@@ -2455,7 +2695,12 @@
   MBMeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
   if (!set_ptr)
     return MB_ENTITY_NOT_FOUND;
+#ifdef MOAB_WITH_REFCOUNT
+  if (set_ptr->remove_parent( parent_meshset ))
+    decrement_reference_count( &parent_meshset, 1 );
+#else
   set_ptr->remove_parent( parent_meshset );
+#endif
   return MB_SUCCESS;
 }
 
@@ -2465,7 +2710,12 @@
   MBMeshSet* set_ptr = get_mesh_set( sequence_manager(), meshset );
   if (!set_ptr)
     return MB_ENTITY_NOT_FOUND;
+#ifdef MOAB_WITH_REFCOUNT
+  if (set_ptr->remove_child( child_meshset ))
+    decrement_reference_count( &child_meshset, 1 );
+#else
   set_ptr->remove_child( child_meshset );
+#endif
   return MB_SUCCESS;
 }
 
@@ -2897,3 +3147,265 @@
                          tag_array,         num_tags,
                          tag_storage,       amortized_tag_storage );
 }
+
+#ifdef MOAB_WITH_REFCOUNT
+
+MBErrorCode MBCore::increment_reference_count( const MBEntityHandle* array, size_t count )
+{
+  MBErrorCode result = MB_SUCCESS, tmp;
+  for (size_t i = 0; i < count; ++i) {
+    MBEntitySequence* seq;
+    tmp = sequence_manager()->find( array[i], seq );
+    if (MB_SUCCESS != tmp)
+      result = tmp;
+    else if (!seq->is_valid_entity(array[i]))
+      result = MB_ENTITY_NOT_FOUND;
+    else
+      seq->increment_reference_count( array[i] );
+  }
+  return result;
+}
+
+MBErrorCode MBCore::decrement_reference_count( const MBEntityHandle* array, size_t count )
+{
+  MBErrorCode result = MB_SUCCESS, tmp;
+  for (size_t i = 0; i < count; ++i) {
+    MBEntitySequence* seq;
+    tmp = sequence_manager()->find( array[i], seq );
+    if (MB_SUCCESS != tmp)
+      result = tmp;
+    else if (!seq->is_valid_entity(array[i]))
+      result = MB_ENTITY_NOT_FOUND;
+    else
+      seq->decrement_reference_count( array[i] );
+  }
+  return result;
+}
+
+unsigned MBCore::get_reference_count( MBEntityHandle handle )
+{
+  MBEntitySequence* seq;
+  MBErrorCode rval = sequence_manager()->find( handle, seq );
+  return MB_SUCCESS == rval ? seq->get_reference_count(handle) : 0;
+}
+
+MBErrorCode MBCore::decrement_all_referenced_entities( MBEntityHandle handle,
+                                   const std::vector<MBTag>& handle_tags )
+{
+  MBEntitySequence* seq;
+  MBErrorCode rval = sequence_manager()->find( handle, seq );
+  if (MB_SUCCESS != rval)
+    return rval;
+  
+  seq->decrement_all_referenced_entities( handle, a_entity_factory() );
+    
+  rval = a_entity_factory()->decrement_referenced_entities( handle );
+  if (MB_SUCCESS != rval) {
+    seq->increment_all_referenced_entities( handle, a_entity_factory() );
+    return rval;
+  }
+  
+  std::vector<MBEntityHandle> tag_data;
+  for (std::vector<MBTag>::const_iterator i = handle_tags.begin(); 
+       i != handle_tags.end(); ++i) {
+    int size;
+    tag_get_size( *i, size );
+    size /= sizeof(MBEntityHandle);
+    tag_data.resize( size );
+    rval = tag_server()->get_data( *i, &handle, 1, &tag_data[0] );
+    if (MB_SUCCESS == rval) 
+      decrement_reference_count( &tag_data[0], size );
+  }
+  return MB_SUCCESS;
+}
+
+
+MBErrorCode MBCore::increment_all_referenced_entities( MBEntityHandle handle,
+                                   const std::vector<MBTag>& handle_tags )
+{
+  MBEntitySequence* seq;
+  MBErrorCode rval = sequence_manager()->find( handle, seq );
+  if (MB_SUCCESS != rval)
+    return rval;
+  
+  seq->increment_all_referenced_entities( handle, a_entity_factory() );
+    
+  rval = a_entity_factory()->increment_referenced_entities( handle );
+  if (MB_SUCCESS != rval) {
+    seq->decrement_all_referenced_entities( handle, a_entity_factory() );
+    return rval;
+  }
+  
+  std::vector<MBEntityHandle> tag_data;
+  for (std::vector<MBTag>::const_iterator i = handle_tags.begin(); 
+       i != handle_tags.end(); ++i) {
+    int size;
+    tag_get_size( *i, size );
+    size /= sizeof(MBEntityHandle);
+    tag_data.resize( size );
+    rval = tag_server()->get_data( *i, &handle, 1, &tag_data[0] );
+    if (MB_SUCCESS == rval) 
+      increment_reference_count( &tag_data[0], size );
+  }
+  return MB_SUCCESS;
+}
+
+#else
+
+MBErrorCode MBCore::increment_reference_count( const MBEntityHandle* , size_t  )
+{
+  abort();
+  return MB_FAILURE;
+}
+
+MBErrorCode MBCore::decrement_reference_count( const MBEntityHandle* , size_t  )
+{
+  abort();
+  return MB_FAILURE;
+}
+
+unsigned MBCore::get_reference_count( MBEntityHandle  )
+{
+  abort();
+  return (unsigned)-1;
+}
+
+MBErrorCode MBCore::decrement_all_referenced_entities( MBEntityHandle,
+                                   const std::vector<MBTag>&  )
+{
+  abort();
+  return MB_FAILURE;
+}
+
+
+MBErrorCode MBCore::increment_all_referenced_entities( MBEntityHandle ,
+                                   const std::vector<MBTag>&  )
+{
+  abort();
+  return MB_FAILURE;
+}
+
+#endif
+
+
+MBErrorCode MBCore::find_all_referencing_entities( MBEntityHandle entity,
+                                                   MBRange& results )
+{
+  MBErrorCode rval;
+  MBRange entities;
+
+    // if entity is a vertex, check all connectivity lists
+  if (TYPE_FROM_HANDLE(entity) == MBVERTEX) {
+    for (MBEntityType t = MBEDGE; t < MBENTITYSET; ++t) {
+      if (t == MBPOLYHEDRON)
+        continue;
+      entities.clear();
+      rval = get_entities_by_type( 0, t, entities );
+      if (MB_SUCCESS != rval)
+        return rval;
+      for (MBRange::iterator i = entities.begin(); i != entities.end(); ++i) {
+        const MBEntityHandle* conn;
+        int len;
+        rval = get_connectivity( *i, conn, len );
+        if (MB_SUCCESS != rval)
+          return rval;
+        if (std::find( conn, conn+len, entity ) - conn < len)
+          results.insert( *i );
+      }
+    }
+  }
+  
+    // if entity type is a face, check polyhedron connectivity
+  if (MBCN::Dimension( TYPE_FROM_HANDLE(entity) ) == 2) {
+    entities.clear();
+    rval = get_entities_by_type( 0, MBPOLYHEDRON, entities );
+    if (MB_SUCCESS != rval)
+      return rval;
+    for (MBRange::iterator i = entities.begin(); i != entities.end(); ++i) {
+      const MBEntityHandle* conn;
+      int len;
+      rval = get_connectivity( *i, conn, len );
+      if (MB_SUCCESS != rval)
+        return rval;
+      if (std::find( conn, conn+len, entity ) - conn < len)
+        results.insert( *i );
+    }
+  }
+  
+    // check all adjacnecy data
+  entities.clear();
+  rval = get_entities_by_handle( 0, entities );
+  if (MB_SUCCESS != rval)
+    return rval;
+  
+  for (MBRange::iterator i = entities.begin(); i != entities.end(); ++i) {
+    const MBEntityHandle* adj;
+    int len;
+    rval = a_entity_factory()->get_adjacencies( *i, adj, len );
+    if (MB_SUCCESS != rval)
+      return rval;
+    
+    if (std::find( adj, adj+len, entity ) - adj < len)
+      results.insert( *i );
+  }
+  
+    // check set contents
+  entities.clear();
+  rval = get_entities_by_type( 0, MBENTITYSET, entities );
+  if (MB_SUCCESS != rval)
+    return rval;
+  for (MBRange::iterator i = entities.begin(); i != entities.end(); ++i) {
+    MBRange contents;
+    rval = get_entities_by_handle( *i, contents );
+    if (contents.find( entity ) != contents.end())
+      results.insert( *i );
+  }
+  
+    // if entity is a set, check set parent/child links
+  if (TYPE_FROM_HANDLE(entity) == MBENTITYSET) {
+    for (MBRange::iterator i = entities.begin(); i != entities.end(); ++i) {
+      MBRange parents, children;
+      rval = get_parent_meshsets( *i, parents );
+      if (MB_SUCCESS != rval)
+        return rval;
+      rval = get_child_meshsets( *i, children );
+      if (MB_SUCCESS != rval)
+        return rval;
+      if (parents.find(entity) != parents.end() || children.find(entity) != children.end())
+        results.insert( *i );
+    }
+  }
+  
+    // check all handle tags
+  std::vector<MBTag> tags;
+  rval = tag_server()->get_tags( MB_TYPE_HANDLE, tags );
+  while (!tags.empty()) {
+    MBTag tag = tags.back();
+    tags.pop_back();
+    int size;
+    rval = tag_get_size( tag, size );
+    if (MB_SUCCESS != rval)
+      return rval;
+    std::vector<MBEntityHandle> tag_values(size/sizeof(MBEntityHandle));;
+    
+    for (MBEntityType t = MBVERTEX; t <= MBENTITYSET; ++t) {
+      entities.clear();
+      rval = get_entities_by_type_and_tag( 0, t, &tag, 0, 1, entities );
+      if (MB_SUCCESS != rval)
+        return rval;
+  
+      for (MBRange::iterator i = entities.begin(); i != entities.end(); ++i) {
+        rval = tag_get_data( tag, &*i, 1, &tag_values[0] );
+        if (MB_SUCCESS != rval)
+          return rval;
+        if (std::find(tag_values.begin(), tag_values.end(), entity) != tag_values.end())
+          results.insert( *i );
+      }
+    }
+  }
+  
+  return MB_SUCCESS;
+}
+
+    
+    

Modified: MOAB/trunk/MBCore.hpp
===================================================================
--- MOAB/trunk/MBCore.hpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/MBCore.hpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -950,6 +950,17 @@
   virtual const MBProcConfig& proc_config() const 
     { return procInfo; }
 
+  MBErrorCode increment_reference_count( MBEntityHandle h )
+    { return increment_reference_count( &h, 1 ); }
+  MBErrorCode decrement_reference_count( MBEntityHandle h )
+    { return decrement_reference_count( &h, 1 ); }
+  MBErrorCode increment_reference_count( const MBEntityHandle* handles, size_t size );
+  MBErrorCode decrement_reference_count( const MBEntityHandle* handles, size_t size );
+  unsigned get_reference_count( MBEntityHandle handle );
+  MBErrorCode decrement_all_referenced_entities( MBEntityHandle handle, const std::vector<MBTag>& handle_tags );
+  MBErrorCode increment_all_referenced_entities( MBEntityHandle handle, const std::vector<MBTag>& handle_tags );
+
+  MBErrorCode find_all_referencing_entities( MBEntityHandle entity, MBRange& results );
 private:
 
   void estimated_memory_use_internal( const MBRange* ents,
@@ -964,6 +975,8 @@
                             unsigned long* tag_storage,
                             unsigned long* amortized_tag_storage );
 
+  MBErrorCode delete_entity( MBEntityHandle handle );
+
   const MBProcConfig procInfo;
 
     //! database init and de-init routines

Modified: MOAB/trunk/MBMeshSet.cpp
===================================================================
--- MOAB/trunk/MBMeshSet.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/MBMeshSet.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -274,6 +274,11 @@
       mAdjFact->remove_adjacency(*iter, mEntityHandle);
     }
   }
+#ifdef MOAB_WITH_REFCOUNT
+  for (MBRange::iterator i = mRange.begin(); i != mRange.end(); ++i)
+    mAdjFact->decrement_reference_count( *i );
+#endif
+    
   mRange.clear();
   return MB_SUCCESS;
 }
@@ -286,7 +291,17 @@
 {
   int i;
   for(i = 0; i < num_entities; i++)
+#ifndef MOAB_WITH_REFCOUNT
     mRange.insert(entities[i]);
+#else
+  {
+    MBRange::iterator j = MBRange::lower_bound( mRange.begin(), mRange.end(), entities[i] );
+    if (j == mRange.end() || *j != entities[i]) {
+      mRange.insert( entities[i] );
+      mAdjFact->increment_reference_count( entities[i] );
+    }
+  }
+#endif
 
   if(tracking() && mAdjFact)
   {
@@ -301,8 +316,27 @@
                                              MBEntityHandle mEntityHandle,
                                              AEntityFactory* mAdjFact )
 {
-
+#ifdef MOAB_WITH_REFCOUNT
+  if (entities.size() > mRange.size()) {
+    MBRange::const_iterator i;
+    for (i = mRange.begin(); i != mRange.end(); ++i)
+      mAdjFact->decrement_reference_count( * i );
+    
+    mRange.merge( entities );
+    for (i = mRange.begin(); i != mRange.end(); ++i)
+      mAdjFact->increment_reference_count( * i );
+  }
+  else {
+    // do this in this way because we expect duplicate to be empty
+    MBRange duplicate = mRange.intersect( entities );
+    for (MBRange::const_iterator i = entities.begin(); i != entities.end(); ++i)
+      if (duplicate.find(*i) == duplicate.end())
+        mAdjFact->increment_reference_count( *i );
+     mRange.merge(entities);
+  }
+#else
   mRange.merge(entities);
+#endif
   
   if(tracking() && mAdjFact)
   {
@@ -325,6 +359,9 @@
     if(found != mRange.end())
     {
       mRange.erase(found);
+#ifdef MOAB_WITH_REFCOUNT
+      mAdjFact->decrement_reference_count( *iter );
+#endif
       if(tracking() && mAdjFact)
         mAdjFact->remove_adjacency(*iter, mEntityHandle);
     }
@@ -345,6 +382,9 @@
     if(found != mRange.end())
     {
       mRange.erase(found);
+#ifdef MOAB_WITH_REFCOUNT
+      mAdjFact->decrement_reference_count( entities[i] );
+#endif
       if(tracking() && mAdjFact)
         mAdjFact->remove_adjacency(entities[i], mEntityHandle);
     }
@@ -368,6 +408,12 @@
                                           MBEntityHandle mEntityHandle,
                                           AEntityFactory* mAdjFact )
 {
+#ifdef MOAB_WITH_REFCOUNT
+  MBRange::const_iterator i;
+  for (i = mRange.begin(); i != mRange.end(); ++i)
+    mAdjFact->decrement_reference_count( * i );
+#endif    
+
   MBRange other_range;
   meshset_2->get_entities(other_range);
 
@@ -384,6 +430,11 @@
     mRange.insert(*iter);
   }
 
+#ifdef MOAB_WITH_REFCOUNT
+  for (i = mRange.begin(); i != mRange.end(); ++i)
+    mAdjFact->increment_reference_count( * i );
+#endif    
+
   //track owner
   if(tracking() && mAdjFact)
   {
@@ -417,6 +468,10 @@
 MBErrorCode MBMeshSet_Vector::clear( MBEntityHandle mEntityHandle, 
                                      AEntityFactory* mAdjFact)
 {
+#ifdef MOAB_WITH_REFCOUNT
+  mAdjFact->decrement_reference_count( &mVector[0], mVector.size() );
+#endif
+
   if(tracking() && mAdjFact)
   {
     for(std::vector<MBEntityHandle>::iterator iter = mVector.begin();
@@ -453,6 +508,10 @@
   mVector.resize(prev_size + num_entities);
   std::copy(entities, entities+num_entities, &mVector[prev_size]);
 
+#ifdef MOAB_WITH_REFCOUNT
+  mAdjFact->increment_reference_count( entities, num_entities );
+#endif
+
   if(tracking() && mAdjFact)
   {
     for(int i = 0; i < num_entities; i++)
@@ -471,6 +530,11 @@
   unsigned int prev_size = mVector.size();
   mVector.resize(prev_size + entities.size());
   std::copy(entities.begin(), entities.end(), &mVector[prev_size]);
+
+#ifdef MOAB_WITH_REFCOUNT
+  for (MBRange::const_iterator i = entities.begin(); i != entities.end(); ++i)
+    mAdjFact->increment_reference_count( *i );
+#endif
   
   if(tracking() && mAdjFact)
   {
@@ -492,6 +556,9 @@
   {
     if(entities.find(*iter) != entities.end())
     {
+#ifdef MOAB_WITH_REFCOUNT
+      mAdjFact->decrement_reference_count( *iter );
+#endif
       if(tracking() && mAdjFact)
         mAdjFact->remove_adjacency(*iter, mEntityHandle);
       iter = mVector.erase(iter);
@@ -515,6 +582,9 @@
     temp_iter = std::find( mVector.begin(), mVector.end(), entities[i]); 
     if( temp_iter != mVector.end() )
     {
+#ifdef MOAB_WITH_REFCOUNT
+      mAdjFact->decrement_reference_count( *temp_iter );
+#endif
       if(tracking() && mAdjFact)
         mAdjFact->remove_adjacency(entities[i], mEntityHandle);
       mVector.erase(temp_iter);
@@ -537,6 +607,10 @@
                                          MBEntityHandle mEntityHandle,
                                          AEntityFactory* mAdjFact )
 {
+#ifdef MOAB_WITH_REFCOUNT
+  mAdjFact->decrement_reference_count( &mVector[0], mVector.size() );
+#endif
+
   MBRange other_range;
   meshset_2->get_entities(other_range);
 
@@ -563,6 +637,10 @@
       mAdjFact->remove_adjacency(*iter, mEntityHandle);
   }
 
+#ifdef MOAB_WITH_REFCOUNT
+  mAdjFact->increment_reference_count( &mVector[0], mVector.size() );
+#endif
+
   return MB_SUCCESS;
 }
 
@@ -581,3 +659,60 @@
        + mVector.capacity()*sizeof(MBEntityHandle);
 }
 
+#ifdef MOAB_WITH_REFCOUNT
+
+void MBMeshSet::increment_all_referenced_entities( AEntityFactory* f )
+{
+  int count;
+  const MBEntityHandle* array;
+  
+  array = get_children(count);
+  f->increment_reference_count( array, count );
+  
+  array = get_parents(count);
+  f->increment_reference_count( array, count );
+  
+  if (vector_based())
+    reinterpret_cast<MBMeshSet_Vector* >(this)->increment_all_referenced_entities( f );
+  else
+    reinterpret_cast<MBMeshSet_MBRange*>(this)->increment_all_referenced_entities( f );
+}
+
+void MBMeshSet::decrement_all_referenced_entities( AEntityFactory* f )
+{
+  int count;
+  const MBEntityHandle* array;
+  
+  array = get_children(count);
+  f->decrement_reference_count( array, count );
+  
+  array = get_parents(count);
+  f->decrement_reference_count( array, count );
+  
+  if (vector_based())
+    reinterpret_cast<MBMeshSet_Vector* >(this)->decrement_all_referenced_entities( f );
+  else
+    reinterpret_cast<MBMeshSet_MBRange*>(this)->decrement_all_referenced_entities( f );
+}
+    
+void MBMeshSet_Vector::increment_all_referenced_entities( AEntityFactory* f )
+{
+  f->increment_reference_count( &mVector[0], mVector.size() );
+}
+void MBMeshSet_Vector::decrement_all_referenced_entities( AEntityFactory* f )
+{
+  f->decrement_reference_count( &mVector[0], mVector.size() );
+}
+
+void MBMeshSet_MBRange::increment_all_referenced_entities( AEntityFactory* f )
+{
+  for (MBRange::const_iterator i = mRange.begin(); i != mRange.end(); ++i)
+    f->increment_reference_count( *i );
+}
+void MBMeshSet_MBRange::decrement_all_referenced_entities( AEntityFactory* f )
+{
+  for (MBRange::const_iterator i = mRange.begin(); i != mRange.end(); ++i)
+    f->decrement_reference_count( *i );
+}
+
+#endif

Modified: MOAB/trunk/MBMeshSet.hpp
===================================================================
--- MOAB/trunk/MBMeshSet.hpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/MBMeshSet.hpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -208,6 +208,11 @@
   
   inline unsigned long get_memory_use() const;
 
+#ifdef MOAB_WITH_REFCOUNT
+  void increment_all_referenced_entities( AEntityFactory* f );
+  void decrement_all_referenced_entities( AEntityFactory* f );
+#endif
+
 protected:
 
   unsigned long parent_child_memory_use() const;
@@ -308,7 +313,7 @@
   \
   inline unsigned int num_entities_by_dimension(int dimesion) const; \
   \
-  unsigned long get_memory_use() const;
+  unsigned long get_memory_use() const;  
 
 
 
@@ -323,6 +328,11 @@
 
   MESH_SET_VIRTUAL_FUNCTIONS
 
+#ifdef MOAB_WITH_REFCOUNT
+  void decrement_all_referenced_entities( AEntityFactory* f);
+  void increment_all_referenced_entities( AEntityFactory* f);
+#endif
+
 private:
   MBRange mRange;
 
@@ -339,6 +349,11 @@
 
   MESH_SET_VIRTUAL_FUNCTIONS
 
+#ifdef MOAB_WITH_REFCOUNT
+  void decrement_all_referenced_entities( AEntityFactory* f);
+  void increment_all_referenced_entities( AEntityFactory* f);
+#endif
+
 private:
   static void vector_to_range( std::vector<MBEntityHandle>& vect, MBRange& range );
 

Modified: MOAB/trunk/MBReadUtil.cpp
===================================================================
--- MOAB/trunk/MBReadUtil.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/MBReadUtil.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -36,6 +36,20 @@
 
 unsigned  MBReadUtil::parallel_rank() const
   { return mMB->proc_config().rank(); }
+   
+  /** Update reference counts for connectivity links.  Does nothing if 
+   *  not compiled with reference counting enabled.   
+   */
+MBErrorCode MBReadUtil::increment_reference_count( 
+                               const MBEntityHandle* ent_array,
+                               size_t num_ent )
+{
+#ifdef MOAB_WITH_REFCOUNT
+  return mMB->increment_reference_count( ent_array, num_ent );
+#else
+  return MB_SUCCESS;
+#endif
+}
 
 MBErrorCode MBReadUtil::get_node_arrays(
     const int /*num_arrays*/,

Modified: MOAB/trunk/MBReadUtil.hpp
===================================================================
--- MOAB/trunk/MBReadUtil.hpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/MBReadUtil.hpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -88,6 +88,12 @@
       int*& last_index_array,
       MBEntityHandle*& connectivity_array
       );
+   
+  /** Update reference counts for connectivity links.  Does nothing if 
+   *  not compiled with reference counting enabled.   
+   */
+  virtual MBErrorCode increment_reference_count( const MBEntityHandle* ent_array,
+                                                 size_t num_ent );
 
   MBErrorCode create_entity_sets(
     MBEntityID num_sets,

Modified: MOAB/trunk/MBReadUtilIface.hpp
===================================================================
--- MOAB/trunk/MBReadUtilIface.hpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/MBReadUtilIface.hpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -109,6 +109,12 @@
       MBEntityHandle*& connectivity_array 
    ) = 0;
    
+  /** Update reference counts for connectivity links.  Does nothing if 
+   *  not compiled with reference counting enabled.   
+   */
+  virtual MBErrorCode increment_reference_count( const MBEntityHandle* ent_array,
+                                                 size_t num_ent ) = 0;
+  
   virtual MBErrorCode create_entity_sets(
     MBEntityID num_sets,
     const unsigned* set_flags,

Modified: MOAB/trunk/MBTest.cpp
===================================================================
--- MOAB/trunk/MBTest.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/MBTest.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -1333,6 +1333,13 @@
     if (MB_SUCCESS != rval) 
       return rval;
   }
+
+#ifdef MOAB_WITH_REFCOUNT
+  MBCore* core = dynamic_cast<MBCore*>(MB);
+  for (int i = 0; i < num_sets; ++i)
+    if (core->get_reference_count(sets[i]) != 1)
+      return MB_FAILURE;
+#endif
   
     // test adding child meshsets
     
@@ -1362,7 +1369,7 @@
   if (!compare_lists( list, sets+1, 2 ))
     return MB_FAILURE;
     // try adding child again
-  rval = MB->add_child_meshset( sets[0], sets[1] );
+  rval = MB->add_child_meshset( sets[0], sets[2] );
   if (MB_SUCCESS != rval) return rval;
   list.clear();
   rval = MB->get_child_meshsets( sets[0], list );
@@ -1379,7 +1386,7 @@
   if (!compare_lists( list, sets+1, 3 ))
     return MB_FAILURE;
     // try adding child again
-  rval = MB->add_child_meshset( sets[0], sets[1] );
+  rval = MB->add_child_meshset( sets[0], sets[3] );
   if (MB_SUCCESS != rval) return rval;
   list.clear();
   rval = MB->get_child_meshsets( sets[0], list );
@@ -1395,6 +1402,14 @@
   if (MB_SUCCESS != rval) return rval;
   if (!compare_lists( list, sets+1, 4 ))
     return MB_FAILURE;
+
+#ifdef MOAB_WITH_REFCOUNT
+  for (int i = 1; i < 5; ++i)
+    if (core->get_reference_count(sets[i]) != 2)
+      return MB_FAILURE;
+#endif
+
+
   
     // make sure range query returns same result
   std::sort( list.begin(), list.end() );
@@ -1443,6 +1458,12 @@
   if (!list.empty())
     return MB_FAILURE;
 
+#ifdef MOAB_WITH_REFCOUNT
+  for (int i = 1; i < 5; ++i)
+    if (core->get_reference_count(sets[i]) != 1)
+      return MB_FAILURE;
+#endif
+
   
     // test adding parent meshsets
     
@@ -1472,7 +1493,7 @@
   if (!compare_lists( list, sets+1, 2 ))
     return MB_FAILURE;
     // try adding parent again
-  rval = MB->add_parent_meshset( sets[0], sets[1] );
+  rval = MB->add_parent_meshset( sets[0], sets[2] );
   if (MB_SUCCESS != rval) return rval;
   list.clear();
   rval = MB->get_parent_meshsets( sets[0], list );
@@ -1489,7 +1510,7 @@
   if (!compare_lists( list, sets+1, 3 ))
     return MB_FAILURE;
     // try adding parent again
-  rval = MB->add_parent_meshset( sets[0], sets[1] );
+  rval = MB->add_parent_meshset( sets[0], sets[3] );
   if (MB_SUCCESS != rval) return rval;
   list.clear();
   rval = MB->get_parent_meshsets( sets[0], list );
@@ -1505,6 +1526,12 @@
   if (MB_SUCCESS != rval) return rval;
   if (!compare_lists( list, sets+1, 4 ))
     return MB_FAILURE;
+
+#ifdef MOAB_WITH_REFCOUNT
+  for (int i = 1; i < 5; ++i)
+    if (core->get_reference_count(sets[i]) != 2)
+      return MB_FAILURE;
+#endif
   
     // make sure range query returns same result
   std::sort( list.begin(), list.end() );
@@ -1552,6 +1579,12 @@
   rval = MB->get_parent_meshsets( sets[0], list );
   if (!list.empty())
     return MB_FAILURE;
+
+#ifdef MOAB_WITH_REFCOUNT
+  for (int i = 1; i < 5; ++i)
+    if (core->get_reference_count(sets[i]) != 1)
+      return MB_FAILURE;
+#endif
     
     
     // setup tests of recursive child query
@@ -1582,6 +1615,13 @@
   if (MB_SUCCESS != rval) return rval;
   rval = MB->add_child_meshset( sets[5], sets[7] );
   if (MB_SUCCESS != rval) return rval;
+
+#ifdef MOAB_WITH_REFCOUNT
+  unsigned expref1[num_sets] = { 1, 2, 2, 2, 3, 2, 3, 3, 1, 1 };
+  for (int i = 0; i < num_sets; ++i)
+    if (core->get_reference_count(sets[i]) != expref1[i])
+      return MB_FAILURE;
+#endif
   
     // test query at depth of 1
   list.clear();
@@ -1662,7 +1702,13 @@
   for (int i = 0; i < 5; ++i)
     if (MB_SUCCESS != MB->num_child_meshsets(sets[i], &count) || count)
       return MB_FAILURE;
-     
+
+#ifdef MOAB_WITH_REFCOUNT
+  for (int i = 0; i < num_sets; ++i)
+    if (core->get_reference_count(sets[i]) != 1)
+      return MB_FAILURE;
+#endif
+
     // setup tests of recursive parent query
     //          6       7
     //        /   \   /   \       .
@@ -1691,6 +1737,12 @@
   if (MB_SUCCESS != rval) return rval;
   rval = MB->add_parent_meshset( sets[5], sets[7] );
   if (MB_SUCCESS != rval) return rval;
+
+#ifdef MOAB_WITH_REFCOUNT
+  for (int i = 0; i < num_sets; ++i)
+    if (core->get_reference_count(sets[i]) != expref1[i])
+      return MB_FAILURE;
+#endif
   
     // test query at depth of 1
   list.clear();
@@ -1771,13 +1823,25 @@
   for (int i = 0; i < 5; ++i)
     if (MB_SUCCESS != MB->num_parent_meshsets(sets[i], &count) || count)
       return MB_FAILURE;
-   
+
+#ifdef MOAB_WITH_REFCOUNT
+  for (int i = 0; i < num_sets; ++i)
+    if (core->get_reference_count(sets[i]) != 1)
+      return MB_FAILURE;
+#endif
     
     // test combined parent/child links
 
     // test creation
   rval = MB->add_parent_child( sets[9], sets[8] );
   if (MB_SUCCESS != rval) return rval;
+
+#ifdef MOAB_WITH_REFCOUNT
+  if (core->get_reference_count(sets[9]) != 2 ||
+      core->get_reference_count(sets[8]) != 2)
+    return MB_FAILURE;
+#endif
+
   list.clear();
   rval = MB->get_child_meshsets( sets[9], list );
   if (MB_SUCCESS != rval) return rval;
@@ -1790,6 +1854,7 @@
     return MB_FAILURE;  
 
     // test deletion of parent/child
+#ifndef MOAB_WITH_REFCOUNT
   rval = MB->add_parent_child( sets[7], sets[9] );
   if (MB_SUCCESS != rval) return rval;
   rval = MB->delete_entities( &sets[9], 1 );
@@ -1805,6 +1870,10 @@
   
     // clean up remaining sets
   return MB->delete_entities( sets, 9 );
+#else
+    // clean up remaining sets
+  return MB->delete_entities( sets, 10 );
+#endif
 }
   
 MBErrorCode mb_mesh_sets_set_test( MBInterface* mb )
@@ -1927,6 +1996,19 @@
   if( hexes.size() + tets.size() != dim_3_range.size() )
     return MB_FAILURE;
 
+#ifdef MOAB_WITH_REFCOUNT
+  MBCore* core = dynamic_cast<MBCore*>(MB);
+  if (core->get_reference_count( ms1 ) != 1)
+    return MB_FAILURE;
+  if (core->get_reference_count( ms2 ) != 1)
+    return MB_FAILURE;
+  if (core->get_reference_count( ms3 ) != 1)
+    return MB_FAILURE;
+  std::vector<unsigned> hex_refs;
+  for (MBRange::iterator i = hexes.begin(); i != hexes.end(); ++i)
+    hex_refs.push_back( core->get_reference_count(*i) );
+#endif
+
     //put all hexes in ms1, ms2, ms3
   result = MB->add_entities(ms1, hexes); //add ents in a range 
   if(result != MB_SUCCESS )
@@ -1942,6 +2024,19 @@
   if(result != MB_SUCCESS )
     return result;
 
+#ifdef MOAB_WITH_REFCOUNT
+  if (core->get_reference_count( ms1 ) != 1)
+    return MB_FAILURE;
+  if (core->get_reference_count( ms2 ) != 1)
+    return MB_FAILURE;
+  if (core->get_reference_count( ms3 ) != 1)
+    return MB_FAILURE;
+  std::vector<unsigned>::iterator j = hex_refs.begin();
+  for (MBRange::iterator i = hexes.begin(); i != hexes.end(); ++i, ++j)
+    if (core->get_reference_count(*i) != 3+*j)
+      return MB_FAILURE;
+#endif
+
     //put all tets in ms1, ms2
   if(MB->add_entities(ms1, &tets[0], tets.size()) != MB_SUCCESS )  //add ents in a vector
     return MB_FAILURE;                             //to ordered meshset 
@@ -2069,15 +2164,21 @@
   MB->get_number_entities_by_handle(ms2, num_before);
   vec_iter = tets.begin();
   result = MB->delete_entities( &(*vec_iter), 1);
+#ifdef MOAB_WITH_REFCOUNT
+  if (result == MB_SUCCESS)
+    return MB_FAILURE;
+#else
   if(result != MB_SUCCESS )
     return result;
+#endif
 
   int num_after = 0;
   MB->get_number_entities_by_handle(ms2, num_after);
+#ifndef MOAB_WITH_REFCOUNT
   if( num_before != num_after + 1)
     return MB_FAILURE;
+#endif
 
-
   return MB_SUCCESS;
 
 }
@@ -2987,6 +3088,7 @@
 
   entities.clear();
   MB->get_entities_by_type(0, MBVERTEX, entities);
+  
   unsigned int original_num_nodes = entities.size();
   entities.clear();
   MB->get_entities_by_type(0, MBHEX, entities);
@@ -3005,6 +3107,7 @@
 
   entities.clear();
   MB->get_entities_by_type(0, MBVERTEX, entities);
+  
     // make sure the higher order nodes really were deleted
   if(entities.size() != original_num_nodes)
     return MB_FAILURE;
@@ -3121,17 +3224,38 @@
 
   
   
-  
+  MBEntityHandle file_set;
   file_name = TestDir + "/mbtest1.g";
-  error = MB->load_mesh(file_name.c_str(), NULL, 0);
+  error = MB->load_file(file_name.c_str(), file_set);
   if (error != MB_SUCCESS)
     return error;
+  error = MB->delete_entities( &file_set, 1 );
+  if (MB_SUCCESS != error)
+    return error;
 
     // delete all MBTRI's
+  MBRange tri_sets;
+  MBTag matset_tag;
+  if (MB_SUCCESS == MB->tag_get_handle( MATERIAL_SET_TAG_NAME, matset_tag )) {
+    error = MB->get_entities_by_type_and_tag( 0, MBENTITYSET, &matset_tag, 0, 1, tri_sets, MBInterface::UNION );
+    if (MB_SUCCESS != error)
+      return error;
+//MBRange users2;
+//error = dynamic_cast<MBCore*>(MB)->find_all_referencing_entities( tri_sets.front(), users2 );
+//assert(MB_SUCCESS == error);
+//users2.print();
+    error = MB->delete_entities( tri_sets );
+    if (MB_SUCCESS != error)
+      return error;
+  }
   entities.clear();
   error = MB->get_entities_by_type(0, MBTRI, entities);
   if (MB_SUCCESS != error)
     return error;
+//MBRange users;
+//error = dynamic_cast<MBCore*>(MB)->find_all_referencing_entities( entities.front(), users );
+//assert(MB_SUCCESS == error);
+//users.print();
   error = MB->delete_entities(entities);
   if (MB_SUCCESS != error)
     return error;

Modified: MOAB/trunk/MeshSetSequence.cpp
===================================================================
--- MOAB/trunk/MeshSetSequence.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/MeshSetSequence.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -49,7 +49,13 @@
   
     // allocate storage
   mSets = new unsigned char[SET_SIZE * num_entities];
+#ifdef MOAB_WITH_REFCOUNT
+  mRefCount.clear();
+  mRefCount.resize( num_entities, flags ? 1 : 0 );
+#else
   mFreeEntities.clear();
+#endif
+
   if (flags) {
     mNumEntities = num_entities;
     mFirstFreeIndex = -1;
@@ -60,7 +66,9 @@
     man->notify_not_full( this );
     mNumEntities = 0;
     mFirstFreeIndex = 0;
+#ifndef MOAB_WITH_REFCOUNT
     mFreeEntities.resize( mNumAllocated, true );
+#endif
     for (MBEntityID i = 0; i < num_entities; ++i)
       next_free(i) = i + 1;
     next_free(num_entities-1) = -1; 
@@ -89,7 +97,11 @@
     return 0;
   const MBEntityID index = mFirstFreeIndex;
   
+#ifndef MOAB_WITH_REFCOUNT
   mFreeEntities[index] = false;
+#else
+  mRefCount[index] = 1;
+#endif
   mFirstFreeIndex = next_free(index);
   if (mLastDeletedIndex == index) 
     mLastDeletedIndex = -1;
@@ -98,8 +110,10 @@
   mNumEntities++;
   if (mNumEntities == mNumAllocated) {
     mSequenceManager->notify_full(this);
+#ifndef MOAB_WITH_REFCOUNT
     std::vector<bool> empty;
     mFreeEntities.swap( empty);
+#endif
   }
   
   return get_start_handle() + index;
@@ -110,6 +124,12 @@
   if (!is_valid_entity(handle))
     return;
   const MBEntityID index = handle - get_start_handle();
+
+#ifdef MOAB_WITH_REFCOUNT
+  if (get_reference_count(handle) != 1)
+    return;
+  decrement_reference_count(handle);
+#endif
   
     // free any memory allocated by the MBMeshSet
   deallocate_set( index );
@@ -117,12 +137,17 @@
     // decerement count of valid entities
   if(mNumEntities == mNumAllocated) {
     mSequenceManager->notify_not_full(this);
+#ifndef MOAB_WITH_REFCOUNT
     mFreeEntities.resize( mNumAllocated, false );
+#endif
   }
   --mNumEntities;
 
     // mark this entity as invalid
+
+#ifndef MOAB_WITH_REFCOUNT
   mFreeEntities[index] = true;
+#endif
   
     // Add this entity to the free list.
     // Free list is maintained in sorted order.
@@ -172,7 +197,12 @@
                                       unsigned long& allocated ) const
 {
   used = 0;
-  allocated = sizeof(*this) + mFreeEntities.capacity()/8;
+  allocated = sizeof(*this);
+#ifdef MOAB_WITH_REFCOUNT
+  allocated += mRefCount.capacity() * sizeof(unsigned);
+#else  
+  allocated += mFreeEntities.capacity()/8;
+#endif
   allocated += mNumAllocated * SET_SIZE;
   for (MBEntityHandle h = get_start_handle(); h <= get_end_handle(); ++h) {
     if (is_valid_entity(h)) {
@@ -501,3 +531,16 @@
   number = children.size();
   return result;
 }
+
+#ifdef MOAB_WITH_REFCOUNT
+void MeshSetSequence::decrement_all_referenced_entities( MBEntityHandle handle, AEntityFactory* f)
+{
+  if (is_valid_entity(handle))
+    get_set( handle )->decrement_all_referenced_entities( f );
+}
+void MeshSetSequence::increment_all_referenced_entities( MBEntityHandle handle, AEntityFactory* f)
+{
+  if (is_valid_entity(handle))
+    get_set( handle )->increment_all_referenced_entities( f );
+}
+#endif

Modified: MOAB/trunk/MeshSetSequence.hpp
===================================================================
--- MOAB/trunk/MeshSetSequence.hpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/MeshSetSequence.hpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -64,6 +64,10 @@
   MBErrorCode num_parents ( MBEntityHandle of, int& number, int num_hops ) const;
   MBErrorCode num_children( MBEntityHandle of, int& number, int num_hops ) const;
   
+#ifdef MOAB_WITH_REFCOUNT
+  virtual void decrement_all_referenced_entities( MBEntityHandle , AEntityFactory* );
+  virtual void increment_all_referenced_entities( MBEntityHandle , AEntityFactory* );
+#endif
 private:
 
   void initialize( EntitySequenceManager* seq_man,

Modified: MOAB/trunk/PolyEntitySequence.cpp
===================================================================
--- MOAB/trunk/PolyEntitySequence.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/PolyEntitySequence.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -140,11 +140,17 @@
 
   mNumEntities++;
   if (mNumEntities == mNumAllocated)  {
+#ifndef MOAB_WITH_REFCOUNT
     std::vector<bool> empty;
     mFreeEntities.swap( empty );
+#endif
     mSequenceManager->notify_full(this);
   }
+#ifndef MOAB_WITH_REFCOUNT
   mFreeEntities[handle - get_start_handle()] = false;
+#else
+  mRefCount[handle - get_start_handle()] = 1;
+#endif
   
     // put the connectivity on the end of that array
   polyConn.insert(polyConn.end(), conn, conn+num_conn);
@@ -182,6 +188,12 @@
     // add this handle to the dead list, and zero out its connectivity
   MBEntityID index = entity - mStartEntityHandle;
   if (!is_valid_entity(entity)) return;
+
+#ifdef MOAB_WITH_REFCOUNT
+  if (get_reference_count(entity) != 1) // only referenced by this sequence
+    return;
+  decrement_reference_count(entity);
+#endif
   
   int start_index;
   if (0 == index) start_index = 0;
@@ -191,9 +203,11 @@
 
     // now add it to the dead list
   mDeadEntities.push_back(entity);
+#ifndef MOAB_WITH_REFCOUNT
   if (mFreeEntities.empty())
     mFreeEntities.resize( mNumAllocated, false );
   mFreeEntities[index] = true;
+#endif
 
     // decrement number of entities
   mNumEntities--;
@@ -209,11 +223,17 @@
                                          unsigned long& allocated) const
 {
   allocated = sizeof(*this)
-       + mFreeEntities.capacity() / 8
        + polyConn.capacity() * sizeof(MBEntityHandle)
        + mLastIndex.capacity() * sizeof(int)
        + mDeadEntities.capacity() * sizeof(MBEntityHandle)
        ;
+
+#ifdef MOAB_WITH_REFCOUNT
+  allocated += mRefCount.capacity() * sizeof(unsigned);
+#else
+  allocated += mFreeEntities.capacity() / 8;
+#endif
+
   used = 0;
   for (MBEntityHandle h = get_start_handle(); h <= get_end_handle(); ++h)
     if (is_valid_entity(h))

Added: MOAB/trunk/README.RefCount
===================================================================
--- MOAB/trunk/README.RefCount	                        (rev 0)
+++ MOAB/trunk/README.RefCount	2007-09-25 15:30:46 UTC (rev 1283)
@@ -0,0 +1,19 @@
+This branch replaces the vector<bool> of valid/invalid flags in entity 
+sequences with a vector<unsigned> of reference counts.  A value of zero
+for an entity signifies a hole in the sequence.  A valid entity has a 
+reference count of at least 1, signifying that it is referenced by it's 
+owning EntitySequence.  
+
+This branch contains code to update reference counts for a) entities used in 
+connectivity lists, b) entities contained in sets, c) sets referenced by
+parent/child links, d) downward adjacencies, and e) entities referenced in
+handle-type tag data.  Additionally, this branch contains enhancements to 
+several existing algorithms that benefit from the reference count, including 
+entity deletion, higher-order conversion, merging, etc.
+
+MBTest fails due to one or more bugs while deleting entity sets.  The high-level
+deletion code decrmenents reference counts for contained and parent/child 
+entities.  However, as part of cleaning up adjacencies, updating bi-directional 
+parent/child links, etc. the low-level deletion code clears the set contents, 
+etc.  This results in the reference count to be decremented a *second* time.  
+

Modified: MOAB/trunk/ReadGmsh.cpp
===================================================================
--- MOAB/trunk/ReadGmsh.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/ReadGmsh.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -399,6 +399,8 @@
   {
     memcpy( conn_array, &connectivity[0], connectivity.size() * sizeof(MBEntityHandle) );
   }
+  
+  readMeshIface->increment_reference_count( conn_array, num_elem * node_per_elem );
 
     // Store element IDs
   result = mdbImpl->tag_set_data( globalId, elements, &elem_ids[0] );

Modified: MOAB/trunk/ReadHDF5.cpp
===================================================================
--- MOAB/trunk/ReadHDF5.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/ReadHDF5.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -429,7 +429,9 @@
     return MB_FAILURE;
   }
   
-  rval = convert_id_to_handle( nodeSet, array, (size_t)(nodes_per_elem*count) );
+  rval = convert_id_to_handle( nodeSet, array, (size_t)nodes_per_elem*count );
+  if (MB_SUCCESS == rval) 
+    readUtil->increment_reference_count( array, (size_t)nodes_per_elem*count );
   return rval;
 }
 
@@ -521,7 +523,10 @@
     return MB_FAILURE;
   }
   
-  return convert_id_to_handle( conn_array, (size_t)data_len );
+  rval = convert_id_to_handle( conn_array, (size_t)data_len );
+  if (MB_SUCCESS == rval) 
+    readUtil->increment_reference_count( conn_array, (size_t)data_len );
+  return rval;
 }
 
 template <typename T>

Modified: MOAB/trunk/ReadNCDF.cpp
===================================================================
--- MOAB/trunk/ReadNCDF.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/ReadNCDF.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -905,6 +905,7 @@
       nodesInLoadedBlocks[tmp_ptr[i]] = 1;
       conn[i] = static_cast<MBEntityHandle>(tmp_ptr[i]) + vertexOffset;
     }
+    readMeshIface->increment_reference_count( conn, number_nodes );
       
     readMeshIface->update_adjacencies((*this_it).startMBId, (*this_it).numElements,
                                       ExoIIUtil::VerticesPerElement[(*this_it).elemType], conn);

Modified: MOAB/trunk/ReadSTL.cpp
===================================================================
--- MOAB/trunk/ReadSTL.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/ReadSTL.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -218,6 +218,8 @@
     *connectivity = vertex_map[i->points[2]]; ++connectivity;
   }
   
+  readMeshIface->increment_reference_count( connectivity, 3*triangles.size() );
+  
   return MB_SUCCESS;
 }
 

Modified: MOAB/trunk/ReadVtk.cpp
===================================================================
--- MOAB/trunk/ReadVtk.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/ReadVtk.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -573,6 +573,8 @@
     }
   } 
   
+  readMeshIface->increment_reference_count( conn_array, size[1] - size[0] );
+  
   return MB_SUCCESS;
 }
 
@@ -657,11 +659,11 @@
     MBEntityHandle* conn_array;
     int* index_array = 0;
     
+    long conn_len = 0;
     if (type == MBPOLYGON)
     {
         // Calculate total length of connectivity list
       std::vector<long>::iterator conn_iter2 = conn_iter;
-      long conn_len = 0;
       for (i = 0; i < num_elem; ++i)
       {
         conn_len += *conn_iter2;
@@ -674,6 +676,7 @@
     }
     else
     {
+      conn_len = num_elem * num_vtx;
       result = allocate_elements( num_elem, num_vtx, type, start_handle,
                                   conn_array, elem_list );
     }
@@ -732,8 +735,10 @@
 
       conn_array += num_vtx;
     }
-  }      
 
+    readMeshIface->increment_reference_count( conn_array, conn_len );
+  }
+
   return MB_SUCCESS;
 }
 
@@ -793,6 +798,8 @@
           *conn_array = index + corners[j] + first_vtx;
       }
   
+
+  readMeshIface->increment_reference_count( conn_array, vert_per_elem * num_elems );
   return MB_SUCCESS;
 }
 

Modified: MOAB/trunk/TagServer.cpp
===================================================================
--- MOAB/trunk/TagServer.cpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/TagServer.cpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -591,6 +591,16 @@
   return MB_SUCCESS;
 }
 
+MBErrorCode TagServer::get_tags(MBDataType type, std::vector<MBTag> &all_tags)
+{
+  for (int i = 0; i < MB_TAG_LAST+1; ++i) 
+    for (MBTagId j = 0; j < mTagTable[i].size(); ++j) 
+      if (mTagTable[i][j].is_valid() && mTagTable[i][j].get_data_type() == type)
+        all_tags.push_back( TAG_HANDLE_FROM_ID( j + 1, (MBTagType)i ) );
+
+  return MB_SUCCESS;
+}
+
 MBErrorCode TagServer::get_tags(const MBEntityHandle entity, std::vector<MBTag> &all_tags)
 {
   MBErrorCode result = MB_SUCCESS;

Modified: MOAB/trunk/TagServer.hpp
===================================================================
--- MOAB/trunk/TagServer.hpp	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/TagServer.hpp	2007-09-25 15:30:46 UTC (rev 1283)
@@ -255,6 +255,9 @@
   //! get all the tags which have been defined
   MBErrorCode get_tags(std::vector<MBTag> &all_tags);
   
+  //! get all tags that store a specified data type
+  MBErrorCode get_tags( MBDataType type, std::vector<MBTag>& tags );
+  
     //! get the default value for a given tag
   MBErrorCode get_default_data(const MBTag tag_handle, void *data);
 

Modified: MOAB/trunk/configure.in
===================================================================
--- MOAB/trunk/configure.in	2007-09-25 15:19:35 UTC (rev 1282)
+++ MOAB/trunk/configure.in	2007-09-25 15:30:46 UTC (rev 1283)
@@ -47,7 +47,16 @@
 fi
 AC_DEFINE_UNQUOTED(MB_VERSION_STRING,"${VERSION_STRING}",[MOAB Version String])
 
+################################################################################
+#                              Debugging Features
+################################################################################
+AC_MSG_CHECKING([if reference counting is enabled])
+AC_ARG_ENABLE([refcounts],
+              [AC_HELP_STRING([enable-refcounts],[Enable reference counting])],
+              [DEFINES="$DEFINES -DMOAB_WITH_REFCOUNT"; AC_MSG_RESULT([yes])],
+              [AC_MSG_RESULT([no])])
 
+
 ################################################################################
 #                              Extract libtool config
 ################################################################################




More information about the moab-dev mailing list