gwnavruntime/database/smallptrtrackedcollection.h Source File

smallptrtrackedcollection.h
Go to the documentation of this file.
1 /*
2 * Copyright 2015 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 // ---------- Primary contact: JUBA - secondary contact: NOBODY
8 #ifndef Navigation_SmallPtrTrackedCollection_H
9 #define Navigation_SmallPtrTrackedCollection_H
10 
12 
13 
14 namespace Kaim
15 {
16 
17 // small container that optimize the case of only 1 element
18 // designed to store T*, default constructor and destructor of template class object are not called
19 // no deep copy is made
20 template <class T>
21 class SmallPtrTrackedCollection
22 {
23  KY_DEFINE_NEW_DELETE_OPERATORS(MemStat_NavData)
24 public:
25  SmallPtrTrackedCollection() : m_count(0), m_capacity(1) { m_values.m_multipleValues = KY_NULL; }
26  ~SmallPtrTrackedCollection() { KY_LOG_ERROR_IF(m_count != 0, ("memory leak !")); }
27 
28  KY_INLINE bool IsEmpty() const { return GetCount() == 0; }
29  KY_INLINE KyUInt32 GetCount() const { return m_count; }
30 
31  KY_INLINE T** GetValues() { return m_capacity == 1 ? &m_values.m_oneValue : m_values.m_multipleValues; }
32 
33  void PushBack(MemoryHeap* heap, T* newValue)
34  {
35  if (m_capacity == 1)
36  {
37  if (IsEmpty())
38  {
39  m_count = 1;
40  newValue->SetIndexInCollection(0);
41  m_values.m_oneValue = newValue;
42  return;
43  }
44 
45  T* firstValue = m_values.m_oneValue;
46 
47  // no buffer allocated yet. create 1 of size 4
48  m_values.m_multipleValues = (T**)KY_HEAP_ALLOC(heap, KyUInt32(4 * sizeof(T*)), MemStat_NavData);
49 
50  m_count = 2;
51  m_capacity = 4;
52 
53  m_values.m_multipleValues[0] = firstValue;
54  m_values.m_multipleValues[1] = newValue;
55 
56  newValue->SetIndexInCollection(1);
57  return;
58  }
59 
60  if (m_count == m_capacity)
61  Reserve(heap, 2 * m_capacity);
62 
63  m_values.m_multipleValues[m_count] = newValue;
64  newValue->SetIndexInCollection(m_count);
65  ++m_count;
66 
67  return;
68  }
69 
70  void Reserve(MemoryHeap* heap, KyUInt32 newcapacity)
71  {
72  KY_DEBUG_ASSERTN(newcapacity > m_count, ("no shrinking !"));
73 
74  T** values = (T**)KY_HEAP_ALLOC(heap, newcapacity * (KyUInt32)sizeof(T*), MemStat_NavData);
75 
76  memcpy(values, m_values.m_multipleValues, m_count * sizeof(T*));
77 
78  KY_FREE(m_values.m_multipleValues);
79 
80  m_capacity = (KyUInt16)newcapacity;
81  m_values.m_multipleValues = values;
82  }
83 
84  void ForceClear()
85  {
86  if (m_capacity > 1)
87  {
88  for(KyUInt32 i = 0; i < m_count; ++i)
89  m_values.m_multipleValues[i]->SetIndexInCollection(KyUInt32MAXVAL);
90 
91  KY_FREE(m_values.m_multipleValues);
92  }
93  else
94  {
95  if (m_count != 0)
96  m_values.m_oneValue->SetIndexInCollection(KyUInt32MAXVAL);
97  }
98 
99  m_count = 0;
100  m_capacity = 1;
101  m_values.m_oneValue = KY_NULL;
102  }
103 
104  void SwapWithLastAndPopBack(T* valueToRemove)
105  {
106  const KyUInt32 index = valueToRemove->GetIndexInCollection();
107  const KyUInt32 lastIndex = (KyUInt32)m_count - 1;
108 
109  KY_DEBUG_ASSERTN(index < m_count, ("error"));
110  if (m_capacity > 1)
111  {
112  m_values.m_multipleValues[index]->SetIndexInCollection(KyUInt32MAXVAL);
113 
114  if (index != lastIndex)
115  {
116  // not the last element, swap with effective last
117  m_values.m_multipleValues[lastIndex]->SetIndexInCollection(index);
118  m_values.m_multipleValues[index] = m_values.m_multipleValues[lastIndex];
119  }
120 
121  --m_count;
122  }
123  else
124  {
125  m_values.m_oneValue->SetIndexInCollection(KyUInt32MAXVAL);
126  m_values.m_oneValue = KY_NULL;
127  m_count = 0;
128  }
129  }
130 
131  void GetOwnershipOfData(SmallPtrTrackedCollection& other)
132  {
133  ForceClear();
134 
135  m_values = other.m_values;
136  m_count = other.m_count;
137  m_capacity = other.m_capacity;
138 
139  other.m_values.m_oneValue = KY_NULL;
140  other.m_count = 0;
141  other.m_capacity = 0;
142  }
143 
144 private:
145  union Values
146  {
147  T* m_oneValue;
148  T** m_multipleValues;
149  };
150 
151  Values m_values;
152  KyUInt16 m_count;
153  KyUInt16 m_capacity;
154 };
155 
156 }
157 
158 #endif //Navigation_SmallPtrTrackedCollection_H
159 
#define KY_NULL
Null value.
Definition: types.h:247
Definition: gamekitcrowddispersion.h:20
#define KY_DEFINE_NEW_DELETE_OPERATORS(MemStat)
This macro defines new and delete operators.
Definition: memory.h:137
unsigned short KyUInt16
Type used internally to represent an unsigned 16-bit integer.
Definition: types.h:40
unsigned int KyUInt32
Type used internally to represent an unsigned 32-bit integer.
Definition: types.h:36
#define KyUInt32MAXVAL
The maximum value that can be stored in the KyUInt32 variable type.
Definition: types.h:226