Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 and are inserted in increasing order
26  * - an entity id that was removed is never added again
27  * - modifications (add / delete) are far less frequent then look-ups
28  * - preformance for iteration is important
29  */
30 template<class T> class EntityMap
31 {
32 private:
33  EntityMap(const EntityMap&); // non-copyable
34  EntityMap& operator=(const EntityMap&); // non-copyable
35 
36 public:
38  typedef T mapped_type;
39  template<class K, class V> struct key_val {
40  typedef K first_type;
41  typedef V second_type;
42  K first;
43  V second;
44  };
45  typedef key_val<entity_id_t, T> value_type;
46 
47 private:
48  size_t m_BufferSize; // number of elements in the buffer
49  size_t m_BufferCapacity; // capacity of the buffer
50  value_type* m_Buffer; // vector with all the mapped key-value pairs
51 
52  size_t m_Count; // number of 'valid' entity id's
53 
54 public:
55 
57  {
58  // for entitymap we allocate the buffer right away
59  // with first element in buffer being the Invalid Entity
60  m_Buffer = (value_type*)malloc(sizeof(value_type) * (m_BufferCapacity + 1));
61 
62  // create the first element:
64  m_Buffer[1].first = 0xFFFFFFFF; // ensure end() always has 0xFFFFFFFF
65  }
66  inline ~EntityMap()
67  {
68  free(m_Buffer);
69  }
70 
71  // Iterators
72  template<class U> struct _iter : public std::iterator<std::forward_iterator_tag, U>
73  {
74  U* val;
75  inline _iter(U* init) : val(init) {}
76  inline U& operator*() { return *val; }
77  inline U* operator->() { return val; }
78  inline _iter& operator++() // ++it
79  {
80  ++val;
81  while (val->first == INVALID_ENTITY) ++val; // skip any invalid entities
82  return *this;
83  }
84  inline _iter& operator++(int) // it++
85  {
86  U* ptr = val;
87  ++val;
88  while (val->first == INVALID_ENTITY) ++val; // skip any invalid entities
89  return ptr;
90  }
91  inline bool operator==(_iter other) { return val == other.val; }
92  inline bool operator!=(_iter other) { return val != other.val; }
93  inline operator _iter<U const>() const { return _iter<U const>(val); }
94  };
95 
96  typedef _iter<value_type> iterator;
97  typedef _iter<value_type const> const_iterator;
98 
99  inline iterator begin()
100  {
101  value_type* ptr = m_Buffer + 1; // skip the first INVALID_ENTITY
102  while (ptr->first == INVALID_ENTITY) ++ptr; // skip any other invalid entities
103  return ptr;
104  }
105  inline iterator end()
106  {
107  return iterator(m_Buffer + m_BufferSize);
108  }
109  inline const_iterator begin() const
110  {
111  value_type* ptr = m_Buffer + 1; // skip the first INVALID_ENTITY
112  while (ptr->first == INVALID_ENTITY) ++ptr; // skip any other invalid entities
113  return ptr;
114  }
115  inline const_iterator end() const
116  {
118  }
119 
120  // Size
121  inline bool empty() const { return m_Count == 0; }
122  inline size_t size() const { return m_Count; }
123 
124  // Modification
125  void insert(const key_type key, const mapped_type& value)
126  {
127  if (key >= m_BufferCapacity) // do we need to resize buffer?
128  {
129  size_t newCapacity = m_BufferCapacity + 4096;
130  while (key >= newCapacity) newCapacity += 4096;
131  // always allocate +1 behind the scenes, because end() must have a 0xFFFFFFFF key
132  value_type* mem = (value_type*)realloc(m_Buffer, sizeof(value_type) * (newCapacity + 1));
133  if (!mem)
134  {
135  debug_warn("EntityMap::insert() realloc failed! Out of memory.");
136  throw std::bad_alloc(); // fail to expand and insert
137  }
138  m_BufferCapacity = newCapacity;
139  m_Buffer = mem;
140  goto fill_gaps;
141  }
142  else if (key > m_BufferSize) // weird insert far beyond the end
143  {
144 fill_gaps:
145  // set all entity id's to INVALID_ENTITY inside the new range
146  for (size_t i = m_BufferSize; i <= key; ++i)
147  m_Buffer[i].first = INVALID_ENTITY;
148  m_BufferSize = key; // extend the new size
149  }
150 
151  value_type& item = m_Buffer[key];
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  item.second = value; // overwrite existing
168  }
169  }
170 
171  void erase(iterator it)
172  {
173  value_type* ptr = it.val;
174  if (ptr->first != INVALID_ENTITY)
175  {
176  ptr->first = INVALID_ENTITY;
177  ptr->second.~T(); // call dtor
178  --m_Count;
179  }
180  }
181  void erase(const entity_id_t key)
182  {
183  if (key < m_BufferSize)
184  {
185  value_type* ptr = m_Buffer + key;
186  if (ptr->first != INVALID_ENTITY)
187  {
188  ptr->first = INVALID_ENTITY;
189  ptr->second.~T(); // call dtor
190  --m_Count;
191  }
192  }
193  }
194  inline void clear()
195  {
196  // orphan whole range
197  value_type* ptr = m_Buffer;
199  for (; ptr != end; ++ptr)
200  {
201  if (ptr->first != INVALID_ENTITY)
202  {
203  ptr->first = INVALID_ENTITY;
204  ptr->second.~T(); // call dtor
205  }
206  }
207  m_Count = 0; // no more valid entities
208  }
209 
210  // Operations
211  inline iterator find(const entity_id_t key)
212  {
213  if (key < m_BufferSize) // is this key in the range of existing entitites?
214  {
215  value_type* ptr = m_Buffer + key;
216  if (ptr->first != INVALID_ENTITY)
217  return ptr;
218  }
219  return m_Buffer + m_BufferSize; // return iterator end()
220  }
221  inline const_iterator find(const entity_id_t key) const
222  {
223  if (key < m_BufferSize) // is this key in the range of existing entitites?
224  {
225  const value_type* ptr = m_Buffer + key;
226  if (ptr->first != INVALID_ENTITY)
227  return ptr;
228  }
229  return m_Buffer + m_BufferSize; // return iterator end()
230  }
231  inline size_t count(const entity_id_t key) const
232  {
233  if (key < m_BufferSize)
234  {
235  if (m_Buffer[key].first != INVALID_ENTITY)
236  return 1;
237  }
238  return 0;
239  }
240 };
241 
242 template<class VSerializer>
244 {
245  template<class V>
246  void operator()(ISerializer& serialize, const char* UNUSED(name), EntityMap<V>& value)
247  {
248  size_t len = value.size();
249  serialize.NumberU32_Unbounded("length", (u32)len);
250  for (typename EntityMap<V>::iterator it = value.begin(); it != value.end(); ++it)
251  {
252  serialize.NumberI32_Unbounded("key", it->first);
253  VSerializer()(serialize, "value", it->second);
254  }
255  }
256 
257  template<class V>
258  void operator()(IDeserializer& deserialize, const char* UNUSED(name), EntityMap<V>& value)
259  {
260  value.clear();
261  uint32_t len;
262  deserialize.NumberU32_Unbounded("length", len);
263  for (size_t i = 0; i < len; ++i)
264  {
265  entity_id_t k;
266  V v;
267  deserialize.NumberU32_Unbounded("key", k);
268  VSerializer()(deserialize, "value", v);
269  value.insert(k, v);
270  }
271  }
272 };
273 
274 
275 #endif
iterator begin()
Definition: EntityMap.h:99
size_t size() const
Definition: EntityMap.h:122
U * operator->()
Definition: EntityMap.h:77
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
void erase(iterator it)
Definition: EntityMap.h:171
void insert(const key_type key, const mapped_type &value)
Definition: EntityMap.h:125
const_iterator end() const
Definition: EntityMap.h:115
key_val< entity_id_t, T > value_type
Definition: EntityMap.h:45
EntityMap & operator=(const EntityMap &)
const_iterator find(const entity_id_t key) const
Definition: EntityMap.h:221
entity_id_t key_type
Definition: EntityMap.h:37
Serialization interface; see serialization overview.
Definition: ISerializer.h:120
size_t m_Count
Definition: EntityMap.h:52
void erase(const entity_id_t key)
Definition: EntityMap.h:181
void clear()
Definition: EntityMap.h:194
iterator find(const entity_id_t key)
Definition: EntityMap.h:211
virtual void NumberU32_Unbounded(const char *name, uint32_t &out)
iterator end()
Definition: EntityMap.h:105
Representation of an entity, with the data needed for queries.
_iter(U *init)
Definition: EntityMap.h:75
size_t count(const entity_id_t key) const
Definition: EntityMap.h:231
size_t m_BufferSize
Definition: EntityMap.h:48
T mapped_type
Definition: EntityMap.h:38
value_type * m_Buffer
Definition: EntityMap.h:50
void operator()(ISerializer &serialize, const char *name, EntityMap< V > &value)
Definition: EntityMap.h:246
void operator()(IDeserializer &deserialize, const char *name, EntityMap< V > &value)
Definition: EntityMap.h:258
~EntityMap()
Definition: EntityMap.h:66
bool empty() const
Definition: EntityMap.h:121
bool operator!=(_iter other)
Definition: EntityMap.h:92
pthread_key_t key
Definition: wpthread.cpp:140
#define T(string_literal)
Definition: secure_crt.cpp:70
void NumberU32_Unbounded(const char *name, uint32_t value)
Serialize a number.
Definition: ISerializer.h:171
size_t m_BufferCapacity
Definition: EntityMap.h:49
const_iterator begin() const
Definition: EntityMap.h:109
EntityMap()
Definition: EntityMap.h:56
_iter< value_type const > const_iterator
Definition: EntityMap.h:97
bool operator==(_iter other)
Definition: EntityMap.h:91
_iter< value_type > iterator
Definition: EntityMap.h:96
#define u32
Definition: types.h:41
unsigned int uint32_t
Definition: wposix_types.h:53
void NumberI32_Unbounded(const char *name, int32_t value)
Serialize a number.
Definition: ISerializer.h:176
#define debug_warn(expr)
display the error dialog with the given text.
Definition: debug.h:324
const entity_id_t INVALID_ENTITY
Invalid entity ID.
Definition: Entity.h:36
u32 entity_id_t
Entity ID type.
Definition: Entity.h:24
_iter & operator++(int)
Definition: EntityMap.h:84
_iter & operator++()
Definition: EntityMap.h:78
A fast replacement for map&lt;entity_id_t, T&gt;.
Definition: EntityMap.h:30
Deserialization interface; see serialization overview.
Definition: IDeserializer.h:34