SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MemoryTest.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <memory.h>
3 #include <crtdbg.h>
4 
5 #include "RTree.h"
6 
7 
8 //
9 // MemoryTest.cpp
10 //
11 // This demonstrates a use of RTree
12 //
13 
14 // Use CRT Debug facility to dump memory leaks on app exit
15 #ifdef WIN32
16  // The following macros set and clear, respectively, given bits
17  // of the C runtime library debug flag, as specified by a bitmask.
18  #ifdef _DEBUG
19  #define SET_CRT_DEBUG_FIELD(a) \
20  _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
21  #define CLEAR_CRT_DEBUG_FIELD(a) \
22  _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
23  #else
24  #define SET_CRT_DEBUG_FIELD(a) ((void) 0)
25  #define CLEAR_CRT_DEBUG_FIELD(a) ((void) 0)
26  #endif
27 #endif //WIN32
28 
29 //
30 // Get a random float b/n two values
31 // The returned value is >= min && < max (exclusive of max)
32 // Note this is a low precision random value since it is generated from an int.
33 //
34 static float RandFloat(float a_min, float a_max)
35 {
36  const float ooMax = 1.0f / (float)(RAND_MAX+1);
37 
38  float retValue = ( (float)rand() * ooMax * (a_max - a_min) + a_min);
39 
40  ASSERT(retValue >= a_min && retValue < a_max); // Paranoid check
41 
42  return retValue;
43 }
44 
45 
47 struct Vec3
48 {
50  Vec3() {}
51 
53  Vec3(float a_x, float a_y, float a_z)
54  {
55  v[0] = a_x;
56  v[1] = a_y;
57  v[2] = a_z;
58  }
59 
61  Vec3 operator+ (const Vec3& a_other) const
62  {
63  return Vec3(v[0] + a_other.v[0],
64  v[1] + a_other.v[1],
65  v[2] + a_other.v[2]);
66  }
67 
68  float v[3];
69 };
70 
71 
72 static bool BoxesIntersect(const Vec3& a_boxMinA, const Vec3& a_boxMaxA,
73  const Vec3& a_boxMinB, const Vec3& a_boxMaxB)
74 {
75  for(int axis=0; axis<3; ++axis)
76  {
77  if(a_boxMinA.v[axis] > a_boxMaxB.v[axis] ||
78  a_boxMaxA.v[axis] < a_boxMinB.v[axis])
79  {
80  return false;
81  }
82  }
83  return true;
84 }
85 
86 
88 struct SomeThing
89 {
91  {
93  }
95  {
97  }
98 
101 
102  static int s_outstandingAllocs;
103 };
104 
107 
108 
110 bool _cdecl QueryResultCallback(SomeThing* a_data, void* a_context)
111 {
112  printf("search found %d\n", a_data->m_creationCounter);
113 
114  return true;
115 }
116 
117 
118 int main(int argc, char* argv[])
119 {
120  const int NUM_OBJECTS = 40; // Number of objects in test set, must be > FRAC_OBJECTS for this test
121  const int FRAC_OBJECTS = 4;
122  const float MAX_WORLDSIZE = 10.0f;
123  const float FRAC_WORLDSIZE = MAX_WORLDSIZE / 2;
124 
125  // typedef the RTree useage just for conveniance with iteration
126  typedef RTree<SomeThing*, float, 3> SomeThingTree;
127 
128  ASSERT( NUM_OBJECTS > FRAC_OBJECTS );
129 
130  int index; // general purpose counter, declared here because MSVC 6 is not ansi compliant with 'for' loops.
131  SomeThing* thingArray[NUM_OBJECTS * 2]; // Store objects in another container to test with, sized larger than we need
132 
133  memset(thingArray, 0, sizeof(thingArray)); // Nullify array, size is known here
134 
135 
136  // Create intance of RTree
137 
138  SomeThingTree tree;
139 
140 
141  // Add some nodes
142  int counter = 0;
143  for( index = 0; index < NUM_OBJECTS; ++index )
144  {
145  SomeThing* newThing = new SomeThing;
146 
147  newThing->m_creationCounter = counter++;
148  newThing->m_min = Vec3(RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE));
149  Vec3 extent = Vec3(RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE));
150  newThing->m_max = newThing->m_min + extent;
151 
152  thingArray[counter-1] = newThing;
153 
154  tree.Insert(newThing->m_min.v, newThing->m_max.v, newThing);
155  printf("inserting %d\n", newThing->m_creationCounter);
156  }
157 
158  printf("tree count = %d\n", tree.Count());
159 
160  int numToDelete = NUM_OBJECTS / FRAC_OBJECTS;
161  int numToStep = FRAC_OBJECTS;
162 
163  // Delete some nodes
164  for( index = 0; index < NUM_OBJECTS; index += numToStep )
165  {
166  SomeThing* curThing = thingArray[index];
167 
168  if(curThing)
169  {
170  tree.Remove(curThing->m_min.v, curThing->m_max.v, curThing);
171  printf("removing %d\n", curThing->m_creationCounter);
172 
173  delete curThing;
174  thingArray[index] = NULL;
175  }
176  }
177 
178  printf("tree count = %d\n", tree.Count());
179 
180  // Add some more nodes
181  for( index = 0; index < numToDelete; ++index )
182  {
183  SomeThing* newThing = new SomeThing;
184 
185  newThing->m_creationCounter = counter++;
186  newThing->m_min = Vec3(RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE));
187  Vec3 extent = Vec3(RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE));
188  newThing->m_max = newThing->m_min + extent;
189 
190  thingArray[counter-1] = newThing;
191 
192  tree.Insert(newThing->m_min.v, newThing->m_max.v, newThing);
193  printf("inserting %d\n", newThing->m_creationCounter);
194  }
195 
196  printf("tree count = %d\n", tree.Count());
197 
198  Vec3 searchMin(0,0,0);
199  Vec3 searchMax(FRAC_WORLDSIZE, FRAC_WORLDSIZE, FRAC_WORLDSIZE);
200  tree.Search(searchMin.v, searchMax.v, &QueryResultCallback, NULL);
201 
202  // NOTE: Even better than just dumping text, it would be nice to render the
203  // tree contents and search result for visualization.
204 
205 
206  // List values. Iterator is NOT delete safe
207  SomeThingTree::Iterator it;
208  for( tree.GetFirst(it); !tree.IsNull(it); tree.GetNext(it) )
209  {
210  SomeThing* curThing = tree.GetAt(it);
211 
212  if(BoxesIntersect(searchMin, searchMax, curThing->m_min, curThing->m_max))
213  {
214  printf("brute found %d\n", curThing->m_creationCounter);
215  }
216  }
217 
218  // Delete our nodes, NOTE, we are NOT deleting the tree nodes, just our data
219  // of course the tree will now contain invalid pointers that must not be used any more.
220  for( tree.GetFirst(it); !tree.IsNull(it); tree.GetNext(it) )
221  {
222  SomeThing* removeElem = tree.GetAt(it);
223  if(removeElem)
224  {
225  printf("deleting %d\n", removeElem->m_creationCounter);
226  delete removeElem;
227  }
228  }
229 
230  // Remove all contents (This would have happened automatically during destructor)
231  tree.RemoveAll();
232 
233  if(SomeThing::s_outstandingAllocs > 0)
234  {
235  printf("Memory leak!\n");
236  printf("s_outstandingAllocs = %d\n", SomeThing::s_outstandingAllocs);
237  }
238  else
239  {
240  printf("No memory leaks detected by app\n");
241  }
242 
243  // Wait for keypress on exit so we can read console output
244  getchar();
245 
246 #ifdef WIN32
247  // Use CRT Debug facility to dump memory leaks on app exit
248  SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF );
249 #endif //WIN32
250 
251  return 0;
252 }