GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cache.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 /**
25  * Also contains code that is Copyright 2011 Yahoo! Inc. All rights
26  * reserved.
27  *
28  * Contributed under the iCLA for:
29  * Joseph Gonzalez ([email protected])
30  *
31  */
32 
33 #ifndef GRAPHLAB_CACHE_HPP
34 #define GRAPHLAB_CACHE_HPP
35 
36 #include <algorithm>
37 #include <vector>
38 #include <boost/functional/hash.hpp>
39 
40 #include <boost/bimap.hpp>
41 #include <boost/bimap/list_of.hpp>
42 #include <boost/bimap/unordered_set_of.hpp>
43 
44 
45 #include <graphlab/logger/assertions.hpp>
46 
47 
48 namespace graphlab {
49  namespace cache {
50 
51  // template<typename Cache, typename Source>
52  // struct bind {
53  // typedef Cache cache_type;
54  // typedef typename cache_type::key_type key_type;
55  // typedef typename cache_type::value_type value_type;
56  // cache_type cache;
57  // Source& source;
58  // bind(Source& source, size_t capacity = 100) :
59  // source(source), capacity(capacity) { }
60  // value_type get(const key_type& key) { return cache.get(key, source); }
61  // }; // end of bind
62 
63 
64  template<typename Key, typename Value>
65  class lru {
66  public:
67  typedef Key key_type;
68  typedef Value value_type;
69 
70  typedef boost::bimaps::bimap<
71  boost::bimaps::unordered_set_of<key_type>,
72  boost::bimaps::list_of<value_type> >
73  cache_map_type;
74 
75  typedef typename cache_map_type::iterator iterator_type;
76  typedef typename cache_map_type::value_type pair_type;
77 
78  private:
79  mutable cache_map_type cache_map;
80 
81 
82  public:
83 
84  lru(size_t cache_reserve = 1024) {
85  cache_map.left.rehash(cache_reserve);
86  }
87 
88 
89  size_t size() const { return cache_map.size(); }
90  size_t empty() const { return size() == 0; }
91 
92  iterator_type begin() { return cache_map.begin(); }
93  iterator_type end() { return cache_map.end(); }
94 
95  std::pair<key_type, value_type> evict() {
96  ASSERT_FALSE(cache_map.empty());
97  typedef typename cache_map_type::right_iterator iterator_type;
98  iterator_type iter = cache_map.right.begin();
99  const std::pair<key_type, value_type>
100  result(iter->get_left(), iter->get_right());
101  cache_map.right.erase(iter);
102  return result;
103  } // end of evict
104 
105  std::pair<bool, value_type> evict(const key_type& key) {
106  typedef typename cache_map_type::left_iterator iterator_type;
107  iterator_type iter = cache_map.left.find(key);
108  if(iter == cache_map.left.end())
109  return std::make_pair(false, value_type());
110  const value_type result = iter->get_right();
111  cache_map.left.erase(iter);
112  return std::make_pair(true, result);
113  } // end of evict(key)
114 
115  bool evict(const key_type& key, value_type& ret_value) {
116  typedef typename cache_map_type::left_iterator iterator_type;
117  iterator_type iter = cache_map.left.find(key);
118  if(iter == cache_map.left.end()) return false;
119  ret_value = iter->get_right();
120  cache_map.left.erase(iter);
121  return true;
122  } // end of evict(key)
123 
124 
125  bool contains(const key_type& key) const {
126  typedef typename cache_map_type::left_const_iterator iterator_type;
127  iterator_type iter = cache_map.left.find(key);
128  return iter != cache_map.left.end();
129  } // end of contains
130 
131 
132  // value_type* find(const key_type& key) {
133 
134  // return cache_map.find(key);
135  // }
136 
137  value_type& operator[](const key_type& key) {
138  typedef typename cache_map_type::left_iterator iterator_type;
139  iterator_type iter = cache_map.left.find(key);
140  if(iter != cache_map.left.end()) { // already in cache
141  // move it to the end
142  cache_map.right.relocate(cache_map.right.end(),
143  cache_map.project_right(iter));
144  return iter->get_right();
145  } else {
146  // add it to the cache
147  // Get the true entry from the source
148  typedef typename cache_map_type::value_type pair_type;
149  cache_map.insert(pair_type(key, value_type()));
150  return cache_map.left[key];
151  }
152  } // end of oeprator[]
153 
154  const value_type& operator[](const key_type& key) const {
155  typedef typename cache_map_type::left_const_iterator iterator_type;
156  iterator_type iter = cache_map.left.find(key);
157  if(iter != cache_map.left.end()) { // already in cache
158  // move it to the end
159  cache_map.right.relocate(cache_map.right.end(),
160  cache_map.project_right(iter));
161  return iter->get_right();
162  }
163  logstream(LOG_FATAL) << "Key not found!" << std::endl;
164  assert(false);
165  } // end of oeprator[]
166 
167  bool get(const key_type& key, value_type& ret_value) {
168  typedef typename cache_map_type::left_iterator iterator_type;
169  iterator_type iter = cache_map.left.find(key);
170  if(iter != cache_map.left.end()) { // already in cache
171  ret_value = iter->get_right();
172  // move it to the end
173  cache_map.right.relocate(cache_map.right.end(),
174  cache_map.project_right(iter));
175  return true;
176  } else return false;
177  } // end of get
178 
179  }; // end of class lru
180 
181 
182 
183 
184 
185  template<typename Key, typename Value>
186  class associative {
187  public:
188  typedef Key key_type;
189  typedef Value value_type;
190 
191 
192  private:
193  std::vector<key_type> keys;
194  std::vector<value_type> values;
195  std::vector<bool> is_set;
196  size_t size_;
197  boost::hash<key_type> hash_function;
198 
199  public:
200 
201  associative(size_t cache_size = 1024) :
202  keys(cache_size), values(cache_size),
203  is_set(cache_size), size_(0) { }
204 
205  size_t size() { return size_; }
206 
207 
208  bool evict_slot(const key_type& key,
209  key_type& ret_key, value_type& ret_value) {
210  const size_t index = hash_function(key) % keys.size();
211  if(is_set[index]) {
212  ret_key = keys[index]; ret_value = values[index];
213  is_set[index] = false;
214  return true;
215  } else return false;
216  } // end of evict_slot
217 
218  std::pair<bool, value_type> evict(const key_type& key) {
219  const size_t index = hash_function(key) % keys.size();
220  if(is_set[index] && key[index] == key) {
221  is_set[index] = false;
222  return std::make_pair(true, values[index]);
223  } else {
224  return std::make_pair(false, value_type());
225  }
226  } // end of evict(key)
227 
228  bool evict(const key_type& key, value_type& ret_value) {
229  const size_t index = hash_function(key) % keys.size();
230  if(is_set[index] && key[index] == key) {
231  is_set[index] = false;
232  ret_value = values[index];
233  return true;
234  } else {
235  return false;
236  }
237  }
238 
239  bool contains(const key_type& key) const {
240  const size_t index = hash_function(key) % keys.size();
241  return is_set[index] && keys[index] == key;
242  } // end of contains
243 
244 
245  value_type& operator[](const key_type& key) {
246  const size_t index = hash_function(key) % keys.size();
247  if(is_set[index]) {
248  ASSERT_TRUE(key == keys[index]);
249  return values[index];
250  } else {
251  keys[index] = key;
252  is_set[index] = true;
253  values[index] = value_type();
254  return values[index];
255  }
256  } // end of oeprator[]
257 
258  const value_type& operator[](const key_type& key) const {
259  const size_t index = hash_function(key) % keys.size();
260  if(is_set[index]) {
261  ASSERT_TRUE(key == keys[index]);
262  return values[index];
263  } else {
264  logstream(LOG_FATAL) << "Key not found!" << std::endl;
265  return value_type();
266  }
267  } // end of oeprator[]
268 
269  bool get(const key_type& key, value_type& ret_value) {
270  const size_t index = hash_function(key) % keys.size();
271  if(is_set[index] && keys[index] == key) {
272  ret_value = values[index];
273  return true;
274  } else {
275  return false;
276  }
277  } // end of get
278 
279  }; // end of class associative
280 
281 
282 
283 
284  }; // end of cache namespace
285 }; // end of graphlab namespace
286 
287 #endif
288 
289 
290