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 
23 
24 /**
25  * A fast replacement for map<entity_id_t, T>.
26  * We make the following assumptions:
27  * - entity id's (keys) are unique
28  * - modifications (add / delete) are far less frequent then look-ups
29  * - preformance for iteration is important
30  */
31 template<class T> class EntityMap
32 {
33 private:
34  EntityMap(const EntityMap&); // non-copyable
35  EntityMap& operator=(const EntityMap&); // non-copyable
36 
37 public:
39  typedef T mapped_type;
40  template<class K, class V> struct key_val {
41  typedef K first_type;
42  typedef V second_type;
43  K first;
44  V second;
45  };
46  typedef key_val<entity_id_t, T> value_type;
47 
48 private:
49  size_t m_BufferSize; // number of elements in the buffer
50  size_t m_BufferCapacity; // capacity of the buffer
51  value_type* m_Buffer; // vector with all the mapped key-value pairs
52 
53  size_t m_Count; // number of 'valid' entity id's
54 
55 public:
56 
57  inline EntityMap() : m_BufferSize(1), m_BufferCapacity(4096), m_Count(0)
58  {
59  // for entitymap we allocate the buffer right away
60  // with first element in buffer being the Invalid Entity
61  m_Buffer = (value_type*)malloc(sizeof(value_type) * (m_BufferCapacity + 1));
62 
63  // create the first element:
64  m_Buffer[0].first = INVALID_ENTITY;
65  m_Buffer[1].first = 0xFFFFFFFF; // ensure end() always has 0xFFFFFFFF
66  }
67  inline ~EntityMap()
68  {
69  free(m_Buffer);
70  }
71 
72  // Iterators
73  template<class U> struct _iter : public std::iterator<std::forward_iterator_tag, U>
74  {
75  U* val;
76  inline _iter(U* init) : val(init) {}
77  inline U& operator*() { return *val; }
78  inline U* operator->() { return val; }
79  inline _iter& operator++() // ++it
80  {
81  ++val;
82  while (val->first == INVALID_ENTITY) ++val; // skip any invalid entities
83  return *this;
84  }
85  inline _iter& operator++(int) // it++
86  {
87  U* ptr = val;
88  ++val;
89  while (val->first == INVALID_ENTITY) ++val; // skip any invalid entities
90  return ptr;
91  }
92  inline bool operator==(_iter other) { return val == other.val; }
93  inline bool operator!=(_iter other) { return val != other.val; }
94  inline operator _iter<U const>() const { return _iter<U const>(val); }
95  };
96 
97  typedef _iter<value_type> iterator;
98  typedef _iter<value_type const> const_iterator;
99 
100  inline iterator begin()
101  {
102  value_type* ptr = m_Buffer + 1; // skip the first INVALID_ENTITY
103  while (ptr->first == INVALID_ENTITY) ++ptr; // skip any other invalid entities
104  return ptr;
105  }
106  inline iterator end()
107  {
108  return iterator(m_Buffer + m_BufferSize);
109  }
110  inline const_iterator begin() const
111  {
112  value_type* ptr = m_Buffer + 1; // skip the first INVALID_ENTITY
113  while (ptr->first == INVALID_ENTITY) ++ptr; // skip any other invalid entities
114  return ptr;
115  }
116  inline const_iterator end() const
117  {
118  return const_iterator(m_Buffer + m_BufferSize);
119  }
120 
121  // Size
122  inline bool empty() const { return m_Count == 0; }
123  inline size_t size() const { return m_Count; }
124 
125  // Modification
126  void insert(const key_type key, const mapped_type& value)
127  {
128  if (key >= m_BufferCapacity) // do we need to resize buffer?
129  {
130  size_t newCapacity = m_BufferCapacity + 4096;
131  while (key >= newCapacity) newCapacity += 4096;
132  // always allocate +1 behind the scenes, because end() must have a 0xFFFFFFFF key
133  value_type* mem = (value_type*)realloc(m_Buffer, sizeof(value_type) * (newCapacity + 1));
134  if (!mem)
135  {
136  debug_warn("EntityMap::insert() realloc failed! Out of memory.");
137  throw std::bad_alloc(); // fail to expand and insert
138  }
139  m_BufferCapacity = newCapacity;
140  m_Buffer = mem;
141  goto fill_gaps;
142  }
143  else if (key > m_BufferSize) // weird insert far beyond the end
144  {
145 fill_gaps:
146  // set all entity id's to INVALID_ENTITY inside the new range
147  for (size_t i = m_BufferSize; i <= key; ++i)
148  m_Buffer[i].first = INVALID_ENTITY;
149  m_BufferSize = key; // extend the new size
150  }
151 
152  value_type& item = m_Buffer[key];
153  key_type oldKey = item.first;
154  item.first = key;
155  if (key == m_BufferSize) // push_back
156  {
157  ++m_BufferSize; // expand
158  ++m_Count;
159  new (&item.second) mapped_type(value); // copy ctor to init
160  m_Buffer[m_BufferSize].first = 0xFFFFFFFF; // ensure end() always has 0xFFFFFFFF
161  }
162  else if(!item.first) // insert new to middle
163  {
164  ++m_Count;
165  new (&item.second) mapped_type(value); // copy ctor to init
166  }
167  else // set existing value
168  {
169  if (oldKey == INVALID_ENTITY)
170  m_Count++;
171  item.second = value; // overwrite existing
172  }
173  }
174 
175  void erase(iterator it)
176  {
177  value_type* ptr = it.val;
178  if (ptr->first != INVALID_ENTITY)
179  {
180  ptr->first = INVALID_ENTITY;
181  ptr->second.~T(); // call dtor
182  --m_Count;
183  }
184  }
185  void erase(const entity_id_t key)
186  {
187  if (key < m_BufferSize)
188  {
189  value_type* ptr = m_Buffer + key;
190  if (ptr->first != INVALID_ENTITY)
191  {
192  ptr->first = INVALID_ENTITY;
193  ptr->second.~T(); // call dtor
194  --m_Count;
195  }
196  }
197  }
198  inline void clear()
199  {
200  // orphan whole range
201  value_type* ptr = m_Buffer;
202  value_type* end = m_Buffer + m_BufferSize;
203  for (; ptr != end; ++ptr)
204  {
205  if (ptr->first != INVALID_ENTITY)
206  {
207  ptr->first = INVALID_ENTITY;
208  ptr->second.~T(); // call dtor
209  }
210  }
211  m_Count = 0; // no more valid entities
212  }
213 
214  // Operations
215  inline iterator find(const entity_id_t key)
216  {
217  if (key < m_BufferSize) // is this key in the range of existing entitites?
218  {
219  value_type* ptr = m_Buffer + key;
220  if (ptr->first != INVALID_ENTITY)
221  return ptr;
222  }
223  return m_Buffer + m_BufferSize; // return iterator end()
224  }
225  inline const_iterator find(const entity_id_t key) const
226  {
227  if (key < m_BufferSize) // is this key in the range of existing entitites?
228  {
229  const value_type* ptr = m_Buffer + key;
230  if (ptr->first != INVALID_ENTITY)
231  return ptr;
232  }
233  return m_Buffer + m_BufferSize; // return iterator end()
234  }
235  inline size_t count(const entity_id_t key) const
236  {
237  if (key < m_BufferSize)
238  {
239  if (m_Buffer[key].first != INVALID_ENTITY)
240  return 1;
241  }
242  return 0;
243  }
244 };
245 
246 template<typename T>
248 {
249  void operator()(ISerializer& serialize, const char* UNUSED(name), EntityMap<T>& value)
250  {
251  size_t len = value.size();
252  serialize.NumberU32_Unbounded("length", (u32)len);
253  size_t count = 0;
254  for (typename EntityMap<T>::iterator it = value.begin(); it != value.end(); ++it)
255  {
256  serialize.NumberU32_Unbounded("key", it->first);
257  Serializer(serialize, "value", it->second);
258  count++;
259  }
260  // test to see if the entityMap count wasn't wrong
261  // (which causes a crashing deserialisation)
262  ENSURE(count == len);
263  }
264 
265  void operator()(IDeserializer& deserialize, const char* UNUSED(name), EntityMap<T>& 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  T v;
274  deserialize.NumberU32_Unbounded("key", k);
275  Serializer(deserialize, "value", v);
276  value.insert(k, v);
277  }
278  }
279 };
280 
281 
282 #endif
iterator begin()
Definition: EntityMap.h:100
K first
Definition: EntityMap.h:43
U * operator->()
Definition: EntityMap.h:78
Helper templates definitions for serializing/deserializing common objects.
#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:175
void insert(const key_type key, const mapped_type &value)
Definition: EntityMap.h:126
U * val
Definition: EntityMap.h:75
U & operator*()
Definition: EntityMap.h:77
key_val< entity_id_t, T > value_type
Definition: EntityMap.h:46
EntityMap & operator=(const EntityMap &)
entity_id_t key_type
Definition: EntityMap.h:38
Serialization interface; see serialization overview.
Definition: ISerializer.h:120
size_t m_Count
Definition: EntityMap.h:53
void Serializer(S &serialize, const char *name, Args &&... args)
Definition: SerializeTemplates.h:51
void erase(const entity_id_t key)
Definition: EntityMap.h:185
void clear()
Definition: EntityMap.h:198
iterator find(const entity_id_t key)
Definition: EntityMap.h:215
virtual void NumberU32_Unbounded(const char *name, uint32_t &out)
Definition: IDeserializer.cpp:124
iterator end()
Definition: EntityMap.h:106
V second
Definition: EntityMap.h:44
_iter(U *init)
Definition: EntityMap.h:76
size_t m_BufferSize
Definition: EntityMap.h:49
const_iterator begin() const
Definition: EntityMap.h:110
T mapped_type
Definition: EntityMap.h:39
value_type * m_Buffer
Definition: EntityMap.h:51
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
Definition: debug.h:290
Definition: EntityMap.h:40
uint32_t u32
Definition: types.h:39
size_t count(const entity_id_t key) const
Definition: EntityMap.h:235
bool empty() const
Definition: EntityMap.h:122
~EntityMap()
Definition: EntityMap.h:67
const_iterator end() const
Definition: EntityMap.h:116
bool operator!=(_iter other)
Definition: EntityMap.h:93
pthread_key_t key
Definition: wpthread.cpp:140
void operator()(ISerializer &serialize, const char *name, EntityMap< T > &value)
Definition: EntityMap.h:249
#define T(string_literal)
Definition: secure_crt.cpp:77
void NumberU32_Unbounded(const char *name, uint32_t value)
Serialize a number.
Definition: ISerializer.h:171
Definition: SerializeTemplates.h:41
size_t m_BufferCapacity
Definition: EntityMap.h:50
EntityMap()
Definition: EntityMap.h:57
_iter< value_type const > const_iterator
Definition: EntityMap.h:98
bool operator==(_iter other)
Definition: EntityMap.h:92
_iter< value_type > iterator
Definition: EntityMap.h:97
V second_type
Definition: EntityMap.h:42
K first_type
Definition: EntityMap.h:41
unsigned int uint32_t
Definition: wposix_types.h:53
#define debug_warn(expr)
display the error dialog with the given text.
Definition: debug.h:332
size_t size() const
Definition: EntityMap.h:123
const entity_id_t INVALID_ENTITY
Invalid entity ID.
Definition: Entity.h:35
u32 entity_id_t
Entity ID type.
Definition: Entity.h:23
_iter & operator++(int)
Definition: EntityMap.h:85
_iter & operator++()
Definition: EntityMap.h:79
void operator()(IDeserializer &deserialize, const char *name, EntityMap< T > &value)
Definition: EntityMap.h:265
Definition: EntityMap.h:73
A fast replacement for map<entity_id_t, T>.
Definition: EntityMap.h:31
const_iterator find(const entity_id_t key) const
Definition: EntityMap.h:225
Deserialization interface; see serialization overview.
Definition: IDeserializer.h:34