MemoryTest.cpp

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <memory.h>
00003 #include <crtdbg.h>
00004 
00005 #include "RTree.h"
00006 
00007 
00008 //
00009 // MemoryTest.cpp
00010 //
00011 // This demonstrates a use of RTree
00012 //
00013 
00014 // Use CRT Debug facility to dump memory leaks on app exit
00015 #ifdef WIN32
00016   // The following macros set and clear, respectively, given bits
00017   // of the C runtime library debug flag, as specified by a bitmask.
00018   #ifdef   _DEBUG
00019     #define  SET_CRT_DEBUG_FIELD(a) \
00020               _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
00021     #define  CLEAR_CRT_DEBUG_FIELD(a) \
00022               _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
00023   #else
00024     #define  SET_CRT_DEBUG_FIELD(a)   ((void) 0)
00025     #define  CLEAR_CRT_DEBUG_FIELD(a) ((void) 0)
00026   #endif
00027 #endif //WIN32
00028 
00029 //
00030 // Get a random float b/n two values
00031 // The returned value is >= min && < max (exclusive of max)
00032 // Note this is a low precision random value since it is generated from an int.
00033 //
00034 static float RandFloat(float a_min, float a_max)
00035 {
00036   const float ooMax = 1.0f / (float)(RAND_MAX+1);
00037   
00038   float retValue = ( (float)rand() * ooMax * (a_max - a_min) + a_min);
00039 
00040   ASSERT(retValue >= a_min && retValue < a_max); // Paranoid check
00041 
00042   return retValue;
00043 }
00044 
00045 
00047 struct Vec3
00048 {
00050   Vec3() {}
00051 
00053   Vec3(float a_x, float a_y, float a_z)
00054   {
00055     v[0] = a_x;
00056     v[1] = a_y;
00057     v[2] = a_z;
00058   }
00059 
00061   Vec3 operator+ (const Vec3& a_other) const
00062   {
00063     return Vec3(v[0] + a_other.v[0], 
00064                 v[1] + a_other.v[1],
00065                 v[2] + a_other.v[2]);
00066   }  
00067 
00068   float v[3];                                     
00069 };
00070 
00071 
00072 static bool BoxesIntersect(const Vec3& a_boxMinA, const Vec3& a_boxMaxA, 
00073                            const Vec3& a_boxMinB, const Vec3& a_boxMaxB)
00074 {
00075   for(int axis=0; axis<3; ++axis)
00076   {
00077     if(a_boxMinA.v[axis] > a_boxMaxB.v[axis] ||
00078        a_boxMaxA.v[axis] < a_boxMinB.v[axis])
00079     {
00080       return false;
00081     }
00082   }
00083   return true;
00084 }
00085 
00086 
00088 struct SomeThing
00089 {
00090   SomeThing()
00091   {
00092     ++s_outstandingAllocs;
00093   }
00094   ~SomeThing()
00095   {
00096     --s_outstandingAllocs;
00097   }
00098 
00099   int m_creationCounter;                          
00100   Vec3 m_min, m_max;                              
00101 
00102   static int s_outstandingAllocs;                 
00103 };
00104 
00106 int SomeThing::s_outstandingAllocs = 0;
00107 
00108 
00110 bool _cdecl QueryResultCallback(SomeThing* a_data, void* a_context)
00111 {
00112   printf("search found %d\n", a_data->m_creationCounter);
00113   
00114   return true;
00115 }
00116 
00117 
00118 int main(int argc, char* argv[])
00119 {
00120   const int NUM_OBJECTS = 40; // Number of objects in test set, must be > FRAC_OBJECTS for this test
00121   const int FRAC_OBJECTS = 4;
00122   const float MAX_WORLDSIZE = 10.0f;
00123   const float FRAC_WORLDSIZE = MAX_WORLDSIZE / 2;
00124 
00125   // typedef the RTree useage just for conveniance with iteration
00126   typedef RTree<SomeThing*, float, 3> SomeThingTree;
00127 
00128   ASSERT( NUM_OBJECTS > FRAC_OBJECTS );
00129 
00130   int index; // general purpose counter, declared here because MSVC 6 is not ansi compliant with 'for' loops.
00131   SomeThing* thingArray[NUM_OBJECTS * 2]; // Store objects in another container to test with, sized larger than we need
00132 
00133   memset(thingArray, 0, sizeof(thingArray)); // Nullify array, size is known here
00134 
00135 
00136   // Create intance of RTree
00137 
00138   SomeThingTree tree; 
00139 
00140   
00141   // Add some nodes
00142   int counter = 0;
00143   for( index = 0; index < NUM_OBJECTS; ++index )
00144   {
00145     SomeThing* newThing = new SomeThing;
00146 
00147     newThing->m_creationCounter = counter++;
00148     newThing->m_min = Vec3(RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE));
00149     Vec3 extent = Vec3(RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE));
00150     newThing->m_max = newThing->m_min + extent;
00151 
00152     thingArray[counter-1] = newThing;
00153 
00154     tree.Insert(newThing->m_min.v, newThing->m_max.v, newThing);
00155     printf("inserting %d\n", newThing->m_creationCounter);
00156   }
00157 
00158   printf("tree count = %d\n", tree.Count());
00159 
00160   int numToDelete = NUM_OBJECTS / FRAC_OBJECTS;
00161   int numToStep = FRAC_OBJECTS;
00162 
00163   // Delete some nodes
00164   for( index = 0; index < NUM_OBJECTS; index += numToStep )
00165   {
00166     SomeThing* curThing = thingArray[index];
00167 
00168     if(curThing)
00169     {
00170       tree.Remove(curThing->m_min.v, curThing->m_max.v, curThing);
00171       printf("removing %d\n", curThing->m_creationCounter);
00172 
00173       delete curThing;
00174       thingArray[index] = NULL;
00175     }
00176   }
00177 
00178   printf("tree count = %d\n", tree.Count());
00179 
00180   // Add some more nodes
00181   for( index = 0; index < numToDelete; ++index )
00182   {
00183     SomeThing* newThing = new SomeThing;
00184 
00185     newThing->m_creationCounter = counter++;
00186     newThing->m_min = Vec3(RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE));
00187     Vec3 extent = Vec3(RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE));
00188     newThing->m_max = newThing->m_min + extent;
00189     
00190     thingArray[counter-1] = newThing;
00191 
00192     tree.Insert(newThing->m_min.v, newThing->m_max.v, newThing);
00193     printf("inserting %d\n", newThing->m_creationCounter);
00194   }
00195 
00196   printf("tree count = %d\n", tree.Count());
00197 
00198   Vec3 searchMin(0,0,0);
00199   Vec3 searchMax(FRAC_WORLDSIZE, FRAC_WORLDSIZE, FRAC_WORLDSIZE); 
00200   tree.Search(searchMin.v, searchMax.v, &QueryResultCallback, NULL);
00201 
00202   // NOTE: Even better than just dumping text, it would be nice to render the 
00203   // tree contents and search result for visualization.
00204  
00205 
00206   // List values.  Iterator is NOT delete safe
00207   SomeThingTree::Iterator it;
00208   for( tree.GetFirst(it); !tree.IsNull(it); tree.GetNext(it) )
00209   {
00210     SomeThing* curThing = tree.GetAt(it);
00211 
00212     if(BoxesIntersect(searchMin, searchMax, curThing->m_min, curThing->m_max))
00213     {
00214       printf("brute found %d\n", curThing->m_creationCounter);
00215     }
00216   }
00217 
00218   // Delete our nodes, NOTE, we are NOT deleting the tree nodes, just our data
00219   // of course the tree will now contain invalid pointers that must not be used any more.
00220   for( tree.GetFirst(it); !tree.IsNull(it); tree.GetNext(it) )
00221   {
00222     SomeThing* removeElem = tree.GetAt(it);
00223     if(removeElem)
00224     {
00225       printf("deleting %d\n", removeElem->m_creationCounter);
00226       delete removeElem;
00227     }
00228   }
00229 
00230   // Remove all contents (This would have happened automatically during destructor)
00231   tree.RemoveAll();
00232  
00233   if(SomeThing::s_outstandingAllocs > 0)
00234   {
00235     printf("Memory leak!\n");
00236     printf("s_outstandingAllocs = %d\n", SomeThing::s_outstandingAllocs);
00237   }
00238   else
00239   {
00240     printf("No memory leaks detected by app\n");
00241   }
00242 
00243   // Wait for keypress on exit so we can read console output
00244   getchar(); 
00245 
00246 #ifdef WIN32
00247   // Use CRT Debug facility to dump memory leaks on app exit
00248   SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF );
00249 #endif //WIN32
00250 
00251   return 0;
00252 }

Generated on Wed May 5 00:06:30 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6