Apama  10.1.0.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
map_t.hpp
Go to the documentation of this file.
1 /*
2  * Title: bits/map_t.hpp
3  * Description: C++ header-only wrapper for C-ABI data_t type
4  * $Copyright (c) 2015-2017 Software AG, Darmstadt, Germany and/or Software AG USA Inc., Reston, VA, USA, and/or its subsidiaries and/or its affiliates and/or their licensors.$
5  * Use, reproduction, transfer, publication or disclosure is prohibited except as specifically provided for in your License Agreement with Software AG
6  * @Version: $Id: map_t.hpp 310444 2017-06-22 12:21:49Z mben $
7  */
8 
15 #ifndef _DATAT_BITS_INCLUDE_TAG
16 #error Must only be included from sag_connectivity_cpp.hpp, use that instead
17 #endif
18 
36 class map_t: protected sag_underlying_map_t
37 {
38  friend class data_t;
39  friend class Message;
41  static size_t MIN_CAPACITY() { return 8; }
42 protected:
43  typedef sag_underlying_map_table_entry_t item_t;
44  typedef int64_t hash_t;
45 public:
46 
47  template<typename DATA>
48  struct pair
49  {
50  hash_t hash;
51  DATA first;
52  DATA second;
53  };
54 
61  template<typename DATA, typename UNDERLYING, typename PAIR>
62  struct _iterator: public std::iterator<std::bidirectional_iterator_tag, DATA>
63  {
64  friend class map_t;
66  typedef PAIR element_t;
67 
68  _iterator(): tabledata(nullptr), capacity(0), offs(0) {}
69  _iterator(const UNDERLYING &tabledata, size_t capacity, int64_t offs, bool stepToItem=false)
70  : tabledata(tabledata), capacity(capacity), offs(offs)
71  {
72  if (!valid() && stepToItem) {
73  operator++();
74  }
75  }
76 
77  iterator &operator--()
78  {
79  if (offs > -1) {
80  do {
81  --offs;
82  } while (!valid());
83  }
84  return *this;
85  }
86  iterator operator--(int)
87  {
88  iterator tmp(*this);
89  operator--();
90  return tmp;
91  }
92  iterator &operator++()
93  {
94  if (offs < capacity) {
95  do {
96  ++offs;
97  } while (!valid());
98  }
99  return *this;
100  }
101  iterator operator++(int)
102  {
103  iterator tmp(*this);
104  operator++();
105  return tmp;
106  }
107 
108  DATA &key() const { return static_cast<DATA&>(tabledata[offs].key); }
109  DATA &value() const { return static_cast<DATA&>(tabledata[offs].value); }
110 
111  bool operator==(const iterator &other) const
112  {
113  bool b = offs == other.offs;
114  return b;
115  }
116  bool operator!=(const iterator &other) const
117  {
118  bool b = !operator==(other);
119  return b;
120  }
121  element_t &operator*() const
122  {
123  return reinterpret_cast<element_t &>(tabledata[offs]);
124  }
125  element_t *operator->() const
126  {
127  return reinterpret_cast<element_t *>(tabledata + offs);
128  }
129  protected:
131  bool valid() const
132  {
133  return offs >= capacity || offs < 0 || tabledata[offs].hash > 1 || SAG_DATA_EMPTY != tabledata[offs].key.tag;
134  }
135  UNDERLYING tabledata;
136  int64_t capacity;
137  int64_t offs;
138  };
144  typedef pair<data_t> element;
146  typedef pair<const data_t> const_element;
147 
150  {
151  table = nullptr;
152  }
154  explicit map_t(size_t n, const char* name = nullptr);
156  explicit map_t(const char* name) : map_t(0, name)
157  {}
158 
161  {
162  clear();
163  }
164 
168  {
169  map_t tmp;
170  // put us in tmp
171  swap(std::move(tmp));
172  // put other in us (and by extension the null tmp in other)
173  swap(std::move(other));
174  return *this;
175  }
177  map_t(map_t &&other)
178  {
179  table = nullptr;
180  swap(std::move(other));
181  }
182 
184  map_t(std::initializer_list<std::pair<data_t,data_t>> l)
185  {
186  table = nullptr;
187  for (auto it = l.begin(); it != l.end(); ++it) {
188  insert(std::make_pair(it->first.copy(), it->second.copy()));
189  }
190  }
191 
193  void swap(map_t &&other)
194  {
195  std::swap(table, other.table);
196  }
197 
199  void swapName(map_t &&other)
200  {
201  if (other.table && other.table->name) {
202  // Need an empty table to set the name
203  if (!table) resize(0);
204  std::swap(table->name, other.table->name);
205  }
206  }
207 
209  map_t copy() const
210  {
211  map_t newmap(size());
212  for (const_iterator it = begin(); it != end(); ++it) {
213  newmap.insert(std::make_pair(it->first.copy(), it->second.copy()));
214  }
215  newmap.setName(getName());
216  return newmap;
217  }
218 
220  void setName(const char *name)
221  {
222  if (table && table->name) {
223  sag_free_string(table->name);
224  table->name = nullptr;
225  }
226 
227  if (name) {
228  // Need an empty table to set the name
229  if (!table) resize(0);
230  table->name = sag_copy_string(name);
231  }
232  }
233 
235  const char* getName() const
236  {
237  if (!table) return nullptr;
238  return table->name;
239  }
240 
241 private:
243  map_t &operator=(const map_t &other) { abort(); }
245  map_t(const map_t &other) { abort(); }
246 public:
247 
249  bool operator==(const map_t &other) const
250  {
251  if (size() != other.size()) return false;
252  if ((table && table->name) || (other.table && other.table->name)) {
253  if (!(table && table->name) || !(other.table && other.table->name)) return false;
254  if (0 != strcmp(table->name, other.table->name)) return false;
255  }
256  for (const_iterator it = begin(); it != end(); ++it) {
257  const_iterator jt = other.find(it.key());
258  if (jt == other.end()) return false;
259  if (it.value() != jt.value()) return false;
260  }
261  return true;
262  }
263 
265  bool operator!=(const map_t &other) const { return !operator==(other); }
266 
267  /* Iteration:
268  * begin() and end() methods, both const and non-const.
269  * Unordered, so forward iteration only
270  */
272  iterator begin() { return iterator(table?table->table:0, table?table->capacity:0, 0, true); }
274  iterator end() { return iterator(table?table->table:0, table?table->capacity:0, table?table->capacity:0, false); }
276  const_iterator begin() const { return const_iterator(table?table->table:0, table?table->capacity:0, 0, true); }
278  const_iterator end() const { return const_iterator(table?table->table:0, table?table->capacity:0, table?table->capacity:0, false); }
280  const_iterator cbegin() const { return const_iterator(table?table->table:0, table?table->capacity:0, 0, true); }
282  const_iterator cend() const { return const_iterator(table?table->table:0, table?table->capacity:0, table?table->capacity:0, false); }
283 
285  size_t size() const { return table?table->count:0; }
286 
288  bool empty() const { return 0 == size(); }
289 
293  {
294  return maybe_insert(std::pair<data_t&&,data_t&&>(std::move(k), data_t())).first->second;
295  }
296 
300  {
301  return maybe_insert(std::pair<const data_t&,const data_t&>(k, data_t())).first->second;
302  }
305  const data_t &operator[](const data_t &k) const
306  {
307  const_iterator it = find(k);
308  if (it == end()) {
309  throw std::runtime_error("Element not in map");
310  } else {
311  return it.value();
312  }
313  }
316  iterator find(const data_t &k);
317 
320  const_iterator find(const data_t &k) const;
321 
333  std::pair<iterator, bool> insert(const std::pair<data_t&&, data_t&&> &v);
334 
346  std::pair<iterator, bool> insert(data_t&& k, data_t&& v) {
347  return insert(std::make_pair(std::move(k), std::move(v)));
348  }
349 
352  std::pair<iterator, bool> insert(const std::pair<data_t&&, data_t&&> &v, hash_t hash);
353 
358  size_t erase(const data_t &k);
363  void erase(iterator it);
367  void clear();
368 
369 protected:
376  void resize(size_t newsize);
377 
379  void really_insert(item_t &item, const std::pair<data_t&&, data_t&&> &v, hash_t hash);
381  std::pair<iterator, bool> maybe_insert(const std::pair<const data_t&, const data_t&> &v);
383  std::pair<iterator, bool> maybe_insert(const std::pair<data_t&&, data_t&&> &v);
385  std::pair<map_t::const_iterator, map_t::const_iterator> find_for_insert(const data_t &k, hash_t hash) const;
386 
388  bool empty(const item_t &item) const { return 0 == item.hash && SAG_DATA_EMPTY == item.key.tag; }
390  bool empty(const const_iterator::element_t &item) const { return 0 == item.hash && SAG_DATA_EMPTY == item.first.tag; }
392  bool hole(const item_t &item) const { return 1 == item.hash && SAG_DATA_EMPTY == item.key.tag; }
394  bool hole(const const_iterator::element_t &item) const { return 1 == item.hash && SAG_DATA_EMPTY == item.first.tag; }
396  bool live(const item_t &item) const { return SAG_DATA_EMPTY != item.key.tag || item.hash > 1; }
398  bool live(const const_iterator::element_t &item) const { return SAG_DATA_EMPTY != item.first.tag || item.hash > 1; }
399 
401  size_t index(hash_t hash) const
402  {
403  if (!table) return 0;
404  return table->capacity ? hash % table->capacity : 0;
405  }
406 
407 #ifdef _SAG_INTERNAL_UNSUPPORTED_DEBUG
408 public:
409  SAG_CONNECTIVITY_API static size_t clashes;
410  SAG_CONNECTIVITY_API static size_t inserts;
411  SAG_CONNECTIVITY_API static double resizeUsage;
412  SAG_CONNECTIVITY_API static size_t resizes;
413  SAG_CONNECTIVITY_API static size_t max_lookup_clash;
414  SAG_CONNECTIVITY_API static size_t lookups;
415  SAG_CONNECTIVITY_API static size_t lookup_clashes;
416  static double getInsertClashRatio() { return (double)clashes/(double)inserts; }
417  static double getAverageResizeRatio() { return resizeUsage/(double)resizes; }
418  static void resetCounters() { clashes = inserts = resizeUsage = resizes = 0; }
419  static double getAverageLookupProbes() { return 1.0+(double)lookup_clashes/(double)lookups; }
420  static size_t getMaxLookupProbes() { return 1+max_lookup_clash; }
421 #endif
422 };
423 
424 
425 
iterator find(const data_t &k)
Searches the map for an item with the given key and returns an iterator to that position in the map...
std::pair< iterator, bool > insert(const std::pair< data_t &&, data_t && > &v)
Insert a new key/value pair into the map.
const data_t & operator[](const data_t &k) const
Return a reference to the item with the given key.
Definition: map_t.hpp:305
~map_t()
Free the underlying map contents.
Definition: map_t.hpp:160
A container for an payload and associated metadata.
Definition: message.hpp:27
A map class which implements many of the functions on std::map.
Definition: map_t.hpp:36
map_t(std::initializer_list< std::pair< data_t, data_t >> l)
Initialiser list construction.
Definition: map_t.hpp:184
iterator end()
Forward iterator end.
Definition: map_t.hpp:274
pair< const data_t > const_element
The type of an element in a const map.
Definition: map_t.hpp:146
data_t & operator[](data_t &&k)
Return a reference to the item with the given key.
Definition: map_t.hpp:292
void swapName(map_t &&other)
Swap the name of this map and other.
Definition: map_t.hpp:199
const char * getName() const
Get the optional name of this map.
Definition: map_t.hpp:235
const_iterator end() const
Forward const_iterator end.
Definition: map_t.hpp:278
_iterator< const data_t, sag_underlying_map_table_entry_t const *, const pair< const data_t > > const_iterator
The type of iterators on const maps.
Definition: map_t.hpp:142
std::pair< iterator, bool > insert(data_t &&k, data_t &&v)
Insert a new key/value pair into the map.
Definition: map_t.hpp:346
size_t size() const
Returns the number of key/value pairs in the map.
Definition: map_t.hpp:285
void swap(map_t &&other)
Swap the contents of this map and other.
Definition: map_t.hpp:193
const_iterator cbegin() const
Forward const_iterator begin.
Definition: map_t.hpp:280
map_t(const char *name)
Construct an empty map with a name.
Definition: map_t.hpp:156
map_t(map_t &&other)
Move constructor.
Definition: map_t.hpp:177
bool operator!=(const map_t &other) const
Returns false if this map deep-equals other.
Definition: map_t.hpp:265
Forward/reverse and const/non-const iterators are implemented using this class.
Definition: map_t.hpp:62
_iterator< data_t, sag_underlying_map_table_entry_t *, pair< data_t > > iterator
The type of iterators on mutable maps.
Definition: map_t.hpp:140
map_t copy() const
Return a deep copy of this map.
Definition: map_t.hpp:209
void clear()
Empty the map, clean the name and free the underlying data.
iterator begin()
Forward iterator begin.
Definition: map_t.hpp:272
const_iterator cend() const
Forward const_iterator end.
Definition: map_t.hpp:282
pair< data_t > element
The type of an element in a mutable map.
Definition: map_t.hpp:144
bool empty() const
Returns true if the map is empty (size() == 0)
Definition: map_t.hpp:288
size_t erase(const data_t &k)
Remove the item with the specified key.
bool operator==(const map_t &other) const
Returns true if this map deep-equals other.
Definition: map_t.hpp:249
A variant type which can be one of the following:
Definition: data_t.hpp:42
const_iterator begin() const
Forward const_iterator begin.
Definition: map_t.hpp:276
map_t()
Construct an empty map.
Definition: map_t.hpp:149
data_t & operator[](const data_t &k)
Return a reference to the item with the given key.
Definition: map_t.hpp:299
void setName(const char *name)
Set the optional name of this map.
Definition: map_t.hpp:220
Empty.
Definition: sag_connectivity_c.h:36
map_t & operator=(map_t &&other)
Move assignment.
Definition: map_t.hpp:167