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



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020