Turi Create  4.0
hash_map_container.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_HASH_MAP_CONTAINER_H_
7 #define TURI_HASH_MAP_CONTAINER_H_
8 
9 #include <core/parallel/pthread_tools.hpp>
10 #include <core/util/cityhash_tc.hpp>
11 
12 namespace turi {
13 
14 template <typename K, typename V>
15 class EXPORT hash_map;
16 
17 // A two level hash_map
18 template <typename K, typename V>
19 class EXPORT hash_map_container {
20  public:
21  typedef hash_map<K, V> hash_map_type;
22 
23  public:
24  hash_map_container() {
25  num_segments = thread::cpu_count() * std::max<size_t>(1, log2(thread::cpu_count()));
26  maps.resize(num_segments, hash_map_type());
27  }
28 
29  explicit hash_map_container(size_t num_seg) {
30  num_segments = std::min(num_seg, thread::cpu_count()
31  * std::max<size_t>(1, log2(thread::cpu_count())));
32  maps.resize(num_segments, hash_map_type());
33  }
34 
35  hash_map_container(const hash_map_container<K, V>&) = default;
36  hash_map_container& operator=(const hash_map_container<K, V>&) = default;
37 
38  // update the value 'v' of key 'k' using function 'func'.
39  void update(const K& k, const std::function<void (V&)>& func) {
40  size_t seg_id = get_segment_id(k);
41  maps[seg_id].update(k, func);
42  }
43 
44  const V& get(const K& k) const {
45  size_t seg_id = get_segment_id(k);
46  return maps[seg_id].get(k);
47  }
48 
49  inline size_t get_segment_id(const K& k) const {
50  return hash64(k) % num_segments;
51  }
52 
53  void clear() {
54  for (auto& m: maps) {
55  m.clear();
56  }
57  }
58 
59  void save(turi::oarchive& oarc) const {
60  oarc << num_segments << maps;
61  }
62 
63  void load(turi::iarchive& iarc) {
64  iarc >> num_segments >> maps;
65  }
66  private:
67  size_t num_segments;
68  std::vector<hash_map_type> maps;
69 };
70 
71 template <typename K, typename V>
72 class EXPORT hash_map {
73  public:
74  hash_map() = default;
75 
76  hash_map(const hash_map& oth) {
77  umap = oth.umap;
78  }
79 
80  hash_map& operator=(const hash_map& oth) {
81  umap = oth.umap;
82  return *this;
83  }
84 
85  void update(const K& k, const std::function<void (V&)>& func) {
86  lock.lock();
87  auto fit = umap.find(k);
88  if (fit == umap.end()) {
89  fit = umap.insert(std::make_pair(k, default_value)).first;
90  }
91  func(fit->second);
92  lock.unlock();
93  }
94 
95  const V& get(const K& k) const {
96  auto fit = umap.find(k);
97  if (fit == umap.end()) {
98  return default_value;
99  }
100  return fit->second;
101  }
102 
103  void clear() {
104  lock.lock();
105  umap.clear();
106  lock.unlock();
107  }
108 
109  void save(turi::oarchive& oarc) const {
110  oarc << umap;
111  }
112 
113  void load(turi::iarchive& iarc) {
114  iarc >> umap;
115  }
116 
117  private:
119  std::unordered_map<K, V> umap;
120  V default_value = V();
121 };
122 
123 } // namespace turi
124 
125 #endif // TURI_HASH_MAP_CONTAINER_H_
The serialization input archive object which, provided with a reference to an istream, will read from the istream, providing deserialization capabilities.
Definition: iarchive.hpp:60
static size_t cpu_count()
static uint64_t hash64(const char *s, size_t len)
The serialization output archive object which, provided with a reference to an ostream, will write to the ostream, providing serialization capabilities.
Definition: oarchive.hpp:80