GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
synchronized_unordered_map.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 GRAPHLAB_SYNCHRONIZED_UNORDERED_MAP
25 #define GRAPHLAB_SYNCHRONIZED_UNORDERED_MAP
26 #include <vector>
27 #include <boost/unordered_map.hpp>
28 #include <graphlab/parallel/pthread_tools.hpp>
29 
30 namespace graphlab {
31 
32 /// \ingroup util_internal
33 template <typename Data>
34 class synchronized_unordered_map {
35  public:
36  typedef boost::unordered_map<size_t, Data> container;
37  typedef typename container::iterator iterator;
38  typedef typename container::const_iterator const_iterator;
39 
40  typedef std::pair<bool, Data*> datapointer;
41  typedef std::pair<bool, const Data*> const_datapointer;
42  typedef Data value_type;
43  typedef size_t key_type;
44 
45  private:
46  std::vector<container> data;
47  std::vector<rwlock> lock;
48  size_t nblocks;
49  public:
50  synchronized_unordered_map(size_t numblocks):data(numblocks),
51  lock(numblocks),
52  nblocks(numblocks) {
53  for (size_t i = 0;i < numblocks; ++i) {
54  data[i].max_load_factor(1.0);
55  }
56  }
57 
58  std::pair<bool, Data*> find(size_t key) {
59  size_t b = key % nblocks;
60  lock[b].readlock();
61  iterator iter = data[b].find(key);
62  std::pair<bool, Data*> ret = std::make_pair(iter != data[b].end(), &(iter->second));
63  lock[b].rdunlock();
64  return ret;
65  }
66 
67  /**
68  return std::pair<found, iterator>
69  if not found, iterator is invalid
70  */
71  std::pair<bool, const Data*> find(size_t key) const {
72  size_t b = key % nblocks;
73  lock[b].readlock();
74  const_iterator iter = data[b].find(key);
75  std::pair<bool, const Data*> ret = std::make_pair(iter != data[b].end(), &(iter->second));
76  lock[b].rdunlock();
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  lock[b].writelock();
84  data[b].erase(key);
85  lock[b].wrunlock();
86  }
87 
88  template<typename Predicate>
89  void erase_if(size_t key, Predicate pred) {
90  size_t b = key % nblocks;
91  lock[b].writelock();
92  iterator iter = data[b].find(key);
93 
94  if (iter != data[b].end() && pred(iter->second)) data[b].erase(key);
95  lock[b].wrunlock();
96  }
97 
98  value_type& insert(size_t key, const value_type &val) {
99  size_t b = key % nblocks;
100  lock[b].writelock();
101  data[b][key] = val;
102  value_type& ret = data[b][key];
103  lock[b].wrunlock();
104  return ret;
105  }
106 
107  /**
108  returns std::pair<success, iterator>
109  on success, iterator will point to the entry
110  on failure, iterator will point to an existing entry
111  */
112  std::pair<bool, Data*> insert_with_failure_detect(size_t key, const value_type &val) {
113  std::pair<bool, Data*> ret ;
114 
115  size_t b = key % nblocks;
116  lock[b].writelock();
117  //search for it
118  iterator iter = data[b].find(key);
119  // if it not in the table, write and return
120  if (iter == data[b].end()) {
121  data[b][key] = val;
122  ret = std::make_pair(true, &(data[b].find(key)->second));
123  }
124  else {
125  ret = std::make_pair(false, &(iter->second));
126  }
127  lock[b].wrunlock();
128  return ret;
129  }
130 
131  void clear() {
132  for (size_t i = 0;i < data.size(); ++i) {
133  data[i].clear();
134  }
135  }
136 };
137 }
138 #endif
139