Turi Create  4.0
value_container_mapper_internal.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef TURI_VALUE_CONTAINER_MAPPER_INTERNAL_H_
7 #define TURI_VALUE_CONTAINER_MAPPER_INTERNAL_H_
8 
9 #include <vector>
10 #include <map>
11 #include <cmath>
12 #include <set>
13 
14 #include <core/util/code_optimization.hpp>
15 #include <core/util/cityhash_tc.hpp>
16 
17 namespace turi { namespace vc_internal {
18 
19 /* See value_container_mapper.hpp for a full descrition of these things.
20  */
21 
22 /**
23  * \internal
24  * The vc_hashkey class is used to determine the key type for the
25  * value container mapper hash-map lookup, along with optionally
26  * holding the value (if it's used as the key). It also helps tame
27  * google's densehash, which has the odd property that you have to
28  * set an empty and a deleted key; this is problematic for integer
29  * keys.
30  *
31  * The class is specialized based on the type of the key.
32  *
33  * This is the general type, which uses hash_value to store the key.
34  */
35 template <typename T, class IsMatch = void>
36 class vc_hashkey {
37  public:
38  static constexpr bool holds_value() GL_HOT_INLINE { return false; }
39  static constexpr bool use_explicit_delete() GL_HOT_INLINE { return false; }
40  static constexpr bool key_is_exact() GL_HOT_INLINE { return false; }
41 
42  vc_hashkey() {}
43  vc_hashkey(const T& t) GL_HOT_INLINE_FLATTEN : _key(hash64(t)) {}
44 
45  const T& value() const { DASSERT_TRUE(false); return T(); }
46 
47  bool operator==(const vc_hashkey& other) const {
48  return _key == other._key;
49  }
50 
51  bool operator!=(const vc_hashkey& other) const {
52  return !(_key == other._key);
53  }
54 
55  size_t hash() const { return _key; }
56 
57  static constexpr bool is_empty(const vc_hashkey& key) {
58  return !(~key._key);
59  }
60 
61  static constexpr bool is_deleted(const vc_hashkey& key) {
62  return use_explicit_delete() && !(key._key == ~(uint64_t(0)^uint64_t(0x1)));
63  }
64 
65  static vc_hashkey as_empty() {
66  vc_hashkey k;
67  k._key = ~uint64_t(0);
68  return k;
69  }
70 
71  static vc_hashkey as_deleted() {
72  vc_hashkey k;
73  k._key = ~(uint64_t(0)^uint64_t(0x1));
74  return k;
75  }
76 
77  private:
78  uint64_t _key = 0;
79 };
80 
81 /** Integer version of the above.
82  */
83 template <typename T>
84 class vc_hashkey<T, typename std::enable_if<std::is_integral<T>::value>::type> {
85  public:
86  static constexpr bool holds_value() GL_HOT_INLINE { return true; }
87  static constexpr bool use_explicit_delete() GL_HOT_INLINE { return false; }
88  static constexpr bool key_is_exact() GL_HOT_INLINE { return true; }
89 
90  vc_hashkey() {}
91  vc_hashkey(const T& t) : _value(t) {}
92 
93  const T& value() const { return _value; }
94 
95  bool operator==(const vc_hashkey& other) const {
96  return _value == other._value;
97  }
98 
99  bool operator!=(const vc_hashkey& other) const {
100  return _value != other._value;
101  }
102 
103  size_t hash() const { return _value; }
104 
105  static constexpr bool is_empty(const vc_hashkey& key) GL_HOT_INLINE_FLATTEN {
106  return key._value == ~(T(0));
107  }
108 
109  static constexpr bool is_deleted(const vc_hashkey& key) GL_HOT_INLINE_FLATTEN {
110  return use_explicit_delete() && (key._value == (~(T(0)) ^ 1));
111  }
112 
113  static vc_hashkey as_empty() {
114  vc_hashkey k;
115  k._value = ~(T(0));
116  return k;
117  }
118 
119  // This one is never called, as use_explicit_delete = false;
120  static vc_hashkey as_deleted() {
121  vc_hashkey k;
122  k._value = ~(T(0)) ^ 1;
123  return k;
124  }
125 
126  private:
127  T _value = 0;
128 };
129 
130 
131 /** A container that holds the key and the value. This is used in
132  * place of a (key, value) pair.
133  */
134 template <typename T, class IsMatch = void>
136  public:
137 
138  typedef T value_type;
139  typedef vc_hashkey<T> key_type;
140 
142  vc_hashkey_and_value(const T& t) : _key(vc_hashkey<T>(t)), _value(t) {}
143  vc_hashkey_and_value(const vc_hashkey<T>& k, const T& t) : _key(k), _value(t) {}
144 
145  const key_type& key() const { return _key; }
146  const T& value() const { return _value; }
147 
148  private:
149  vc_hashkey<T> _key;
150  T _value;
151 };
152 
153 /** An extension of the key pair to associate it with a value, which
154  * then allows specialization by type. For integer values, this
155  * holds just the integer, which then doubles as the key. For
156  * strings, it holds both the 128 bit non-intersecting hash along
157  * with the string.
158  */
159 template <typename T>
161  T, typename std::enable_if<vc_hashkey<T>::holds_value()>::type> {
162 
163  public:
164 
165  typedef T value_type;
166  typedef vc_hashkey<T> key_type;
167 
169  vc_hashkey_and_value(const T& t) : _key_and_value(vc_hashkey<T>(t)) {}
170  vc_hashkey_and_value(const vc_hashkey<T>& k, const T&) : _key_and_value(k) {}
171 
172  const key_type& key() const { return _key_and_value; }
173  const T& value() const { return _key_and_value.value(); }
174 
175  private:
176  vc_hashkey<T> _key_and_value;
177 };
178 
179 }}
180 
181 #endif /* _VALUE_CONTAINER_MAPPER_H_ */
STL namespace.
static uint64_t hash64(const char *s, size_t len)
#define GL_HOT_INLINE
#define GL_HOT_INLINE_FLATTEN
#define DASSERT_TRUE(cond)
Definition: assertions.hpp:364