Main MRPT website > C++ reference for MRPT 1.9.9
ts_hash_map.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 #pragma once
10 
12 #include <mrpt/utils/mrpt_macros.h>
14 
15 #include <array>
16 
17 namespace mrpt
18 {
19 namespace utils
20 {
21 template <typename KEY, typename VALUE>
23 {
24  bool used;
25  KEY first;
26  VALUE second;
27  ts_map_entry() : used(false), first(KEY()), second() {}
28 };
29 
30 /** hash function used by ts_hash_map. Uses dbj2 method */
31 void reduced_hash(const std::string& value, uint8_t& hash);
32 /** hash function used by ts_hash_map. Uses dbj2 method */
33 void reduced_hash(const std::string& value, uint16_t& hash);
34 /** hash function used by ts_hash_map. Uses dbj2 method */
35 void reduced_hash(const std::string& value, uint32_t& hash);
36 /** hash function used by ts_hash_map. Uses dbj2 method */
37 void reduced_hash(const std::string& value, uint64_t& hash);
38 
39 /** A thread-safe (ts) container which minimally emulates a std::map<>'s [] and
40  * find() methods but which is implemented as a linear vector indexed by a hash
41  * of KEY.
42  * Any custom hash function can be implemented, we don't rely by default on
43  * C++11 std::hash<> due to its limitation in some implementations.
44  *
45  * This implementation is much more efficient than std::map<> when the most
46  * common operation is accesing elements
47  * by KEY with find() or [], and is also thread-safe if different threads
48  * create entries with different hash values.
49  *
50  * The default underlying non-associative container is a "memory-aligned
51  * std::vector<>", but it can be changed to a
52  * standard vector<> or to a deque<> (to avoid memory reallocations) by
53  * changing the template parameter \a VECTOR_T.
54  *
55  * \note Defined in #include <mrpt/utils/ts_hash_map.h>
56  * \ingroup stlext_grp
57  */
58 template <
59  typename KEY, typename VALUE, unsigned int NUM_BYTES_HASH_TABLE = 1,
60  unsigned int NUM_HAS_TABLE_COLLISIONS_ALLOWED = 5,
61  typename VECTOR_T = std::array<
62  std::array<ts_map_entry<KEY, VALUE>, NUM_HAS_TABLE_COLLISIONS_ALLOWED>,
63  1u << (8 * NUM_BYTES_HASH_TABLE)>>
64 class ts_hash_map
65 {
66  public:
67  /** @name Types
68  @{ */
69  typedef ts_hash_map<KEY, VALUE, NUM_BYTES_HASH_TABLE,
70  NUM_HAS_TABLE_COLLISIONS_ALLOWED, VECTOR_T>
71  self_t;
72  typedef KEY key_type;
73  typedef ts_map_entry<KEY, VALUE> value_type;
74  typedef VECTOR_T vec_t;
75 
76  struct iterator;
77  struct const_iterator
78  {
79  public:
81  : m_vec(nullptr), m_parent(nullptr), m_idx_outer(0), m_idx_inner(0)
82  {
83  }
85  const VECTOR_T& vec, const self_t& parent, int idx_outer,
86  int idx_inner)
87  : m_vec(const_cast<VECTOR_T*>(&vec)),
88  m_parent(const_cast<self_t*>(&parent)),
89  m_idx_outer(idx_outer),
90  m_idx_inner(idx_inner)
91  {
92  }
93  const_iterator& operator=(const const_iterator& o)
94  {
95  m_vec = o.m_vec;
96  m_idx_outer = o.m_idx_outer;
97  m_idx_inner = o.m_idx_inner;
98  return *this;
99  }
100  bool operator==(const const_iterator& o) const
101  {
102  return m_vec == o.m_vec && m_idx_outer == o.m_idx_outer &&
103  m_idx_inner == o.m_idx_inner;
104  }
105  bool operator!=(const const_iterator& o) const { return !(*this == o); }
106  const value_type& operator*() const
107  {
108  return (*m_vec)[m_idx_outer][m_idx_inner];
109  }
110  const value_type* operator->() const
111  {
112  return &(*m_vec)[m_idx_outer][m_idx_inner];
113  }
114  inline const_iterator operator++(int)
115  { /* Post: it++ */
116  const_iterator aux = *this;
117  ++(*this);
118  return aux;
119  }
120  inline const_iterator& operator++()
121  { /* pre: ++it */
122  incr();
123  return *this;
124  }
125 
126  protected:
127  VECTOR_T* m_vec;
128  self_t* m_parent;
129  int m_idx_outer, m_idx_inner;
130  void incr()
131  {
132  // This loop ends with the first used entry in the nested arrays, or
133  // an iterator pointing to "end()".
134  do
135  {
136  if (++m_idx_inner >= (int)NUM_HAS_TABLE_COLLISIONS_ALLOWED)
137  {
138  m_idx_inner = 0;
139  m_idx_outer++;
140  }
141  } while (m_idx_outer < (int)m_parent->m_vec.size() &&
142  !(*m_vec)[m_idx_outer][m_idx_inner].used);
143  }
144  };
145 
146  struct iterator : public const_iterator
147  {
148  public:
149  iterator() : const_iterator() {}
150  iterator(VECTOR_T& vec, self_t& parent, int idx_outer, int idx_inner)
151  : const_iterator(vec, parent, idx_outer, idx_inner)
152  {
153  }
154  value_type& operator*()
155  {
156  return (*const_iterator::m_vec)[const_iterator::m_idx_outer]
157  [const_iterator::m_idx_inner];
158  }
159  value_type* operator->()
160  {
161  return &(*const_iterator::m_vec)[const_iterator::m_idx_outer]
162  [const_iterator::m_idx_inner];
163  }
164  inline iterator operator++(int)
165  { /* Post: it++ */
166  iterator aux = *this;
167  ++(*this);
168  return aux;
169  }
171  { /* pre: ++it */
172  const_iterator::incr();
173  return *this;
174  }
175  };
176  /** @} */
177  private:
178  /** The actual container */
179  vec_t m_vec;
180  /** Number of elements accessed with write access so far */
181  size_t m_size;
182 
183  public:
184  /** @name Constructors, read/write access and other operations
185  @{ */
186  //!< Default constructor */
187  ts_hash_map() : m_size(0) {}
188  /** Clear the contents of this container */
189  void clear()
190  {
191  m_size = 0;
192  for (size_t oi = 0; oi < m_vec.size(); oi++)
193  for (size_t ii = 0; ii < NUM_HAS_TABLE_COLLISIONS_ALLOWED; ii++)
194  m_vec[oi][ii] = value_type();
195  }
196 
197  bool empty() const { return m_size == 0; }
198  /** Write/read via [i] operator, that creates an element if it didn't exist
199  * already. */
200  VALUE& operator[](const KEY& key)
201  {
203  NUM_BYTES_HASH_TABLE>::type hash;
204  reduced_hash(key, hash);
205  std::array<ts_map_entry<KEY, VALUE>, NUM_HAS_TABLE_COLLISIONS_ALLOWED>&
206  match_arr = m_vec[hash];
207  for (unsigned int i = 0; i < NUM_HAS_TABLE_COLLISIONS_ALLOWED; i++)
208  {
209  if (!match_arr[i].used)
210  {
211  m_size++;
212  match_arr[i].used = true;
213  match_arr[i].first = key;
214  return match_arr[i].second;
215  }
216  if (match_arr[i].first == key) return match_arr[i].second;
217  }
218  THROW_EXCEPTION("ts_hash_map: too many hash collisions!");
219  }
220  const_iterator find(const KEY& key) const
221  {
223  NUM_BYTES_HASH_TABLE>::type hash;
224  reduced_hash(key, hash);
225  const std::array<ts_map_entry<KEY, VALUE>,
226  NUM_HAS_TABLE_COLLISIONS_ALLOWED>& match_arr =
227  m_vec[hash];
228  for (unsigned int i = 0; i < NUM_HAS_TABLE_COLLISIONS_ALLOWED; i++)
229  {
230  if (match_arr[i].used && match_arr[i].first == key)
231  return const_iterator(m_vec, *this, hash, i);
232  }
233  return this->end();
234  }
235 
237  {
238  const_iterator it(m_vec, *this, 0, -1);
239  ++it;
240  return it;
241  }
243  {
244  return const_iterator(m_vec, *this, m_vec.size(), 0);
245  }
246  iterator begin()
247  {
248  iterator it(m_vec, *this, 0, -1);
249  ++it;
250  return it;
251  }
252  iterator end() { return iterator(m_vec, *this, m_vec.size(), 0); }
253  /** @} */
254 
255 }; // end class ts_hash_map
256 
257 } // End of namespace
258 } // End of namespace
const_iterator end() const
Definition: ts_hash_map.h:242
unsigned __int16 uint16_t
Definition: rptypes.h:44
KEY first
Definition: ts_hash_map.h:25
ts_hash_map()
< Default constructor */
Definition: ts_hash_map.h:187
iterator operator++(int)
A thread-safe (ts) container which minimally emulates a std::map<>&#39;s [] and find() methods but which ...
Definition: ts_hash_map.h:164
GLint * first
Definition: glext.h:3827
#define THROW_EXCEPTION(msg)
const_iterator begin() const
Definition: ts_hash_map.h:236
Scalar * iterator
Definition: eigen_plugins.h:26
Usage: uint_select_by_bytecount<N>type var; allows defining var as a unsigned integer with...
const Scalar * const_iterator
Definition: eigen_plugins.h:27
const_iterator find(const KEY &key) const
Definition: ts_hash_map.h:220
Definition: ts_hash_map.h:22
bool operator==(const mrpt::utils::TCamera &a, const mrpt::utils::TCamera &b)
Definition: TCamera.cpp:204
void clear()
Clear the contents of this container.
Definition: ts_hash_map.h:189
unsigned char uint8_t
Definition: rptypes.h:41
bool operator!=(const mrpt::utils::TCamera &a, const mrpt::utils::TCamera &b)
Definition: TCamera.cpp:211
VALUE & operator[](const KEY &key)
Write/read via [i] operator, that creates an element if it didn&#39;t exist already.
Definition: ts_hash_map.h:200
VALUE second
Definition: ts_hash_map.h:26
bool empty() const
Definition: ts_hash_map.h:197
GLsizei const GLchar ** string
Definition: glext.h:4101
void reduced_hash(const std::string &value, uint8_t &hash)
hash function used by ts_hash_map.
Definition: ts_hash_map.cpp:27
size_t m_size
Number of elements accessed with write access so far.
Definition: ts_hash_map.h:181
vec_t m_vec
The actual container.
Definition: ts_hash_map.h:175
unsigned __int64 uint64_t
Definition: rptypes.h:50
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
ts_map_entry()
Definition: ts_hash_map.h:27
GLsizei const GLfloat * value
Definition: glext.h:4117
unsigned __int32 uint32_t
Definition: rptypes.h:47
GLuint GLuint GLsizei GLenum type
Definition: glext.h:3528
bool used
Definition: ts_hash_map.h:24
std::vector< T1 > operator*(const std::vector< T1 > &a, const std::vector< T2 > &b)
a*b (element-wise multiplication)
Definition: ops_vectors.h:62



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019