Pyrogenesis  trunk
EntityMap.h
Go to the documentation of this file.
1 /* Copyright (C) 2013 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 #ifndef INCLUDED_ENTITYMAP
18 #define INCLUDED_ENTITYMAP
19 
20 #include "Entity.h"
21 
22 /**
23  * A fast replacement for map<entity_id_t, T>.
24  * We make the following assumptions:
25  * - entity id's (keys) are unique
26  * - modifications (add / delete) are far less frequent then look-ups
27  * - preformance for iteration is important
28  */
29 template<class T> class EntityMap
30 {
31 private:
32  EntityMap(const EntityMap&); // non-copyable
33  EntityMap& operator=(const EntityMap&); // non-copyable
34 
35 public:
37  typedef T mapped_type;
38  template<class K, class V> struct key_val {
39  typedef K first_type;
40  typedef V second_type;
41  K first;
42  V second;
43  };
44  typedef key_val<entity_id_t, T> value_type;
45 
46 private:
47  size_t m_BufferSize; // number of elements in the buffer
48  size_t m_BufferCapacity; // capacity of the buffer
49  value_type* m_Buffer; // vector with all the mapped key-value pairs
50 
51  size_t m_Count; // number of 'valid' entity id's
52 
53 public:
54 
55  inline EntityMap() : m_BufferSize(1), m_BufferCapacity(4096), m_Count(0)
56  {
57  // for entitymap we allocate the buffer right away
58  // with first element in buffer being the Invalid Entity
59  m_Buffer = (value_type*)malloc(sizeof(value_type) * (m_BufferCapacity + 1));
60 
61  // create the first element:
62  m_Buffer[0].first = INVALID_ENTITY;
63  m_Buffer[1].first = 0xFFFFFFFF; // ensure end() always has 0xFFFFFFFF
64  }
65  inline ~EntityMap()
66  {
67  free(m_Buffer);
68  }
69 
70  // Iterators
71  template<class U> struct _iter : public std::iterator<std::forward_iterator_tag, U>
72  {
73  U* val;
74  inline _iter(U* init) : val(init) {}
75  inline U& operator*() { return *val; }
76  inline U* operator->() { return val; }
77  inline _iter& operator++() // ++it
78  {
79  ++val;
80  while (val->first == INVALID_ENTITY) ++val; // skip any invalid entities
81  return *this;
82  }
83  inline _iter& operator++(int) // it++
84  {
85  U* ptr = val;
86  ++val;
87  while (val->first == INVALID_ENTITY) ++val; // skip any invalid entities
88  return ptr;
89  }
90  inline bool operator==(_iter other) { return val == other.val; }
91  inline bool operator!=(_iter other) { return val != other.val; }
92  inline operator _iter<U const>() const { return _iter<U const>(val); }
93  };
94 
95  typedef _iter<value_type> iterator;
96  typedef _iter<value_type const> const_iterator;
97 
98  inline iterator begin()
99  {
100  value_type* ptr = m_Buffer + 1; // skip the first INVALID_ENTITY
101  while (ptr->first == INVALID_ENTITY) ++ptr; // skip any other invalid entities
102  return ptr;
103  }
104  inline iterator end()
105  {
106  return iterator(m_Buffer + m_BufferSize);
107  }
108  inline const_iterator begin() const
109  {
110  value_type* ptr = m_Buffer + 1; // skip the first INVALID_ENTITY
111  while (ptr->first == INVALID_ENTITY) ++ptr; // skip any other invalid entities
112  return ptr;
113  }
114  inline const_iterator end() const
115  {
116  return const_iterator(m_Buffer + m_BufferSize);
117  }
118 
119  // Size
120  inline bool empty() const { return m_Count == 0; }
121  inline size_t size() const { return m_Count; }
122 
123  // Modification
124  void insert(const key_type key, const mapped_type& value)
125  {
126  if (key >= m_BufferCapacity) // do we need to resize buffer?
127  {
128  size_t newCapacity = m_BufferCapacity + 4096;
129  while (key >= newCapacity) newCapacity += 4096;
130  // always allocate +1 behind the scenes, because end() must have a 0xFFFFFFFF key
131  value_type* mem = (value_type*)realloc(m_Buffer, sizeof(value_type) * (newCapacity + 1));
132  if (!mem)
133  {
134  debug_warn("EntityMap::insert() realloc failed! Out of memory.");
135  throw std::bad_alloc(); // fail to expand and insert
136  }
137  m_BufferCapacity = newCapacity;
138  m_Buffer = mem;
139  goto fill_gaps;
140  }
141  else if (key > m_BufferSize) // weird insert far beyond the end
142  {
143 fill_gaps:
144  // set all entity id's to INVALID_ENTITY inside the new range
145  for (size_t i = m_BufferSize; i <= key; ++i)
146  m_Buffer[i].first = INVALID_ENTITY;
147  m_BufferSize = key; // extend the new size
148  }
149 
150  value_type& item = m_Buffer[key];
151  key_type oldKey = item.first;
152  item.first = key;
153  if (key == m_BufferSize) // push_back
154  {
155  ++m_BufferSize; // expand
156  ++m_Count;
157  new (&item.second) mapped_type(value); // copy ctor to init
158  m_Buffer[m_BufferSize].first = 0xFFFFFFFF; // ensure end() always has 0xFFFFFFFF
159  }
160  else if(!item.first) // insert new to middle
161  {
162  ++m_Count;
163  new (&item.second) mapped_type(value); // copy ctor to init
164  }
165  else // set existing value
166  {
167  if (oldKey == INVALID_ENTITY)
168  m_Count++;
169  item.second = value; // overwrite existing
170  }
171  }
172 
173  void erase(iterator it)
174  {
175  value_type* ptr = it.val;
176  if (ptr->first != INVALID_ENTITY)
177  {
178  ptr->first = INVALID_ENTITY;
179  ptr->second.~T(); // call dtor
180  --m_Count;
181  }
182  }
183  void erase(const entity_id_t key)
184  {
185  if (key < m_BufferSize)
186  {
187  value_type* ptr = m_Buffer + key;
188  if (ptr->first != INVALID_ENTITY)
189  {
190  ptr->first = INVALID_ENTITY;
191  ptr->second.~T(); // call dtor
192  --m_Count;
193  }
194  }
195  }
196  inline void clear()
197  {
198  // orphan whole range
199  value_type* ptr = m_Buffer;
200  value_type* end = m_Buffer + m_BufferSize;
201  for (; ptr != end; ++ptr)
202  {
203  if (ptr->first != INVALID_ENTITY)
204  {
205  ptr->first = INVALID_ENTITY;
206  ptr->second.~T(); // call dtor
207  }
208  }
209  m_Count = 0; // no more valid entities
210  }
211 
212  // Operations
213  inline iterator find(const entity_id_t key)
214  {
215  if (key < m_BufferSize) // is this key in the range of existing entitites?
216  {
217  value_type* ptr = m_Buffer + key;
218  if (ptr->first != INVALID_ENTITY)
219  return ptr;
220  }
221  return m_Buffer + m_BufferSize; // return iterator end()
222  }
223  inline const_iterator find(const entity_id_t key) const
224  {
225  if (key < m_BufferSize) // is this key in the range of existing entitites?
226  {
227  const value_type* ptr = m_Buffer + key;
228  if (ptr->first != INVALID_ENTITY)
229  return ptr;
230  }
231  return m_Buffer + m_BufferSize; // return iterator end()
232  }
233  inline size_t count(const entity_id_t key) const
234  {
235  if (key < m_BufferSize)
236  {
237  if (m_Buffer[key].first != INVALID_ENTITY)
238  return 1;
239  }
240  return 0;
241  }
242 };
243 
244 template<class VSerializer>
246 {
247  template<class V>
248  void operator()(ISerializer& serialize, const char* UNUSED(name), EntityMap<V>& value)
249  {
250  size_t len = value.size();
251  serialize.NumberU32_Unbounded("length", (u32)len);
252  size_t count = 0;
253  for (typename EntityMap<V>::iterator it = value.begin(); it != value.end(); ++it)
254  {
255  serialize.NumberU32_Unbounded("key", it->first);
256  VSerializer()(serialize, "value", it->second);
257  count++;
258  }
259  // test to see if the entityMap count wasn't wrong
260  // (which causes a crashing deserialisation)
261  ENSURE(count == len);
262  }
263 
264  template<class V>
265  void operator()(IDeserializer& deserialize, const char* UNUSED(name), EntityMap<V>& value)
266  {
267  value.clear();
268  uint32_t len;
269  deserialize.NumberU32_Unbounded("length", len);
270  for (size_t i = 0; i < len; ++i)
271  {
272  entity_id_t k;
273  V v;
274  deserialize.NumberU32_Unbounded("key", k);
275  VSerializer()(deserialize, "value", v);
276  value.insert(k, v);
277  }
278  }
279 };
280 
281 
282 #endif
iterator begin()
Definition: EntityMap.h:98
size_t size() const
Definition: EntityMap.h:121
K first
Definition: EntityMap.h:41
U * operator->()
Definition: EntityMap.h:76
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
Definition: code_annotation.h:38
void erase(iterator it)
Definition: EntityMap.h:173
void insert(const key_type key, const mapped_type &value)
Definition: EntityMap.h:124
U * val
Definition: EntityMap.h:73
U & operator*()
Definition: EntityMap.h:75
const_iterator end() const
Definition: EntityMap.h:114
key_val< entity_id_t, T > value_type
Definition: EntityMap.h:44
EntityMap & operator=(const EntityMap &)
const_iterator find(const entity_id_t key) const
Definition: EntityMap.h:223
entity_id_t key_type
Definition: EntityMap.h:36
Serialization interface; see serialization overview.
Definition: ISerializer.h:120
size_t m_Count
Definition: EntityMap.h:51
void erase(const entity_id_t key)
Definition: EntityMap.h:183
void clear()
Definition: EntityMap.h:196
iterator find(const entity_id_t key)
Definition: EntityMap.h:213
virtual void NumberU32_Unbounded(const char *name, uint32_t &out)
Definition: IDeserializer.cpp:124
iterator end()
Definition: EntityMap.h:104
V second
Definition: EntityMap.h:42
_iter(U *init)
Definition: EntityMap.h:74
size_t count(const entity_id_t key) const
Definition: EntityMap.h:233
size_t m_BufferSize
Definition: EntityMap.h:47
T mapped_type
Definition: EntityMap.h:37
value_type * m_Buffer
Definition: EntityMap.h:49
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
Definition: debug.h:287
Definition: EntityMap.h:38
uint32_t u32
Definition: types.h:39
void operator()(ISerializer &serialize, const char *name, EntityMap< V > &value)
Definition: EntityMap.h:248
void operator()(IDeserializer &deserialize, const char *name, EntityMap< V > &value)
Definition: EntityMap.h:265
~EntityMap()
Definition: EntityMap.h:65
bool empty() const
Definition: EntityMap.h:120
bool operator!=(_iter other)
Definition: EntityMap.h:91
pthread_key_t key
Definition: wpthread.cpp:140
#define T(string_literal)
Definition: secure_crt.cpp:76
void NumberU32_Unbounded(const char *name, uint32_t value)
Serialize a number.
Definition: ISerializer.h:171
size_t m_BufferCapacity
Definition: EntityMap.h:48
const_iterator begin() const
Definition: EntityMap.h:108
EntityMap()
Definition: EntityMap.h:55
_iter< value_type const > const_iterator
Definition: EntityMap.h:96
bool operator==(_iter other)
Definition: EntityMap.h:90
_iter< value_type > iterator
Definition: EntityMap.h:95
V second_type
Definition: EntityMap.h:40
K first_type
Definition: EntityMap.h:39
unsigned int uint32_t
Definition: wposix_types.h:53
Definition: EntityMap.h:245
#define debug_warn(expr)
display the error dialog with the given text.
Definition: debug.h:329
Definition: cache.cpp:318
const entity_id_t INVALID_ENTITY
Invalid entity ID.
Definition: Entity.h:35
u32 entity_id_t
Entity ID type.
Definition: Entity.h:23
void init(ScriptInterface &scriptInterface)
Definition: JSInterface_GUITypes.cpp:260
_iter & operator++(int)
Definition: EntityMap.h:83
_iter & operator++()
Definition: EntityMap.h:77
Definition: EntityMap.h:71
A fast replacement for map<entity_id_t, T>.
Definition: EntityMap.h:29
Deserialization interface; see serialization overview.
Definition: IDeserializer.h:34