GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
synchronized_unordered_map2.hpp
1 /**
2  * Copyright (c) 2009 Carnegie Mellon University.
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an "AS
13  * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14  * express or implied. See the License for the specific language
15  * governing permissions and limitations under the License.
16  *
17  * For more about this software visit:
18  *
19  * http://www.graphlab.ml.cmu.edu
20  *
21  */
22 
23 
24 #ifndef SYNCHRONIZED_UNORDERED_MAP2
25 #define SYNCHRONIZED_UNORDERED_MAP2
26 #include <vector>
27 #include <boost/unordered_map.hpp>
28 #include <graphlab/parallel/pthread_tools.hpp>
29 
30 
31 namespace graphlab {
32 /*
33  \ingroup util_internal
34 An alternate form of the synchronized unordered map, built around the
35 use of critical sections
36 */
37 template <typename Data>
38 class synchronized_unordered_map2 {
39  public:
40  typedef boost::unordered_map<size_t, Data> container;
41  typedef typename container::iterator iterator;
42  typedef typename container::const_iterator const_iterator;
43 
44  typedef std::pair<bool, Data*> datapointer;
45  typedef std::pair<bool, const Data*> const_datapointer;
46  typedef Data value_type;
47  typedef size_t key_type;
48 
49  private:
50  std::vector<container> data;
51  std::vector<rwlock> lock;
52  size_t nblocks;
53  public:
54  synchronized_unordered_map2(size_t numblocks):data(numblocks),
55  lock(numblocks),
56  nblocks(numblocks) {
57  for (size_t i = 0;i < numblocks; ++i) {
58  data[i].max_load_factor(1.0);
59  }
60  }
61 
62  std::pair<bool, Data*> find(size_t key) {
63  size_t b = key % nblocks;
64  iterator iter = data[b].find(key);
65  std::pair<bool, Data*> ret = std::make_pair(iter != data[b].end(), &(iter->second));
66  return ret;
67  }
68 
69  /**
70  return std::pair<found, iterator>
71  if not found, iterator is invalid
72  */
73  std::pair<bool, const Data*> find(size_t key) const {
74  size_t b = key % nblocks;
75  const_iterator iter = data[b].find(key);
76  std::pair<bool, const Data*> ret = std::make_pair(iter != data[b].end(), &(iter->second));
77  return ret;
78  }
79 
80  // care must be taken that you do not access an erased iterator
81  void erase(size_t key) {
82  size_t b = key % nblocks;
83  data[b].erase(key);
84  }
85 
86  template<typename Predicate>
87  void erase_if(size_t key, Predicate pred) {
88  size_t b = key % nblocks;
89  iterator iter = data[b].find(key);
90 
91  if (iter != data[b].end() && pred(iter->second)) data[b].erase(key);
92  }
93 
94  value_type& insert(size_t key, const value_type &val) {
95  size_t b = key % nblocks;
96  data[b][key] = val;
97  value_type& ret = data[b][key];
98  return ret;
99  }
100 
101  void read_critical_section(size_t key) {
102  size_t b = key % nblocks;
103  lock[b].readlock();
104  }
105  void write_critical_section(size_t key) {
106  size_t b = key % nblocks;
107  lock[b].writelock();
108  }
109  void release_critical_section(size_t key) {
110  size_t b = key % nblocks;
111  lock[b].unlock();
112  }
113  /**
114  returns std::pair<success, iterator>
115  on success, iterator will point to the entry
116  on failure, iterator will point to an existing entry
117  */
118  std::pair<bool, Data*> insert_with_failure_detect(size_t key, const value_type &val) {
119  std::pair<bool, Data*> ret ;
120 
121  size_t b = key % nblocks;
122  //search for it
123  iterator iter = data[b].find(key);
124  // if it not in the table, write and return
125  if (iter == data[b].end()) {
126  data[b][key] = val;
127  ret = std::make_pair(true, &(data[b].find(key)->second));
128  }
129  else {
130  ret = std::make_pair(false, &(iter->second));
131  }
132  return ret;
133  }
134 
135  void clear() {
136  for (size_t i = 0;i < data.size(); ++i) {
137  data[i].clear();
138  }
139  }
140 };
141 }
142 #endif
143