MADNESS  0.10.1
dist_cache.h
Go to the documentation of this file.
1 /*
2  This file is part of MADNESS.
3 
4  Copyright (C) 2013 Virginia Tech
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20  For more information please contact:
21 
22  Robert J. Harrison
23  Oak Ridge National Laboratory
24  One Bethel Valley Road
25  P.O. Box 2008, MS-6367
26 
27  email: harrisonrj@ornl.gov
28  tel: 865-241-3937
29  fax: 865-572-0680
30  */
31 
32 #ifndef MADNESS_WORLD_DIST_CACHE_H__INCLUDED
33 #define MADNESS_WORLD_DIST_CACHE_H__INCLUDED
34 
37 #include <madness/world/future.h>
38 
39 namespace madness {
40  namespace detail {
41 
42  /// Distributed caching utility
43 
44  /// This object implements a local, key-value caching mechanism that can
45  /// be used by remote tasks or active messages to move data between
46  /// processes without synchronization. Because cache values are
47  /// retrieved via a \c Future, you can get or set the cache in any
48  /// order. The first call \c get_cache_value or \c set_cache_value or
49  /// will insert the cache element, and the second call to these
50  /// functions will remove it. Therefore, \c set_cache_value and
51  /// get_cache_value can only be called once each per cache value.
52  /// \tparam keyT The key type of the cache
53  template <typename keyT>
54  class DistCache {
55  private:
56 
57  // Forward declarations
58  class Cache;
59  template <typename> class CacheData;
60 
62  ///< The container that holds cache values
64  ///< Cache container datum type
65 
66  static cache_container caches_; ///< Cache container
67 
68  /// Cache interface class
69 
70  /// This base class is used to access derived class values
71  class Cache {
72  public:
73 
74  /// Virtual destructor
75  virtual ~Cache() { }
76 
77  /// Cache data accessor
78 
79  /// \tparam valueT The cached data type
80  /// \return A const reference to the cached future
81  template <typename valueT>
82  const madness::Future<valueT>& get() const {
84  return static_cast<const CacheData<valueT>*>(this)->value();
85  }
86 
87  private:
88 
89  /// Typeid accessor of the derived class
90 
91  /// \return The std::type_info of the derived class
92  virtual const std::type_info& get_type_info() const = 0;
93 
94  }; // class Cache
95 
96  /// Cache value container
97 
98  /// \tparam valueT The data type stored in the cache
99  template <typename valueT>
100  class CacheData : public Cache {
101  private:
102  madness::Future<valueT> value_; ///< Local cached data
103 
104  public:
105 
106  /// Default constructor
107  CacheData() : value_() { }
108 
109  /// Constructor with future initialization
111 
112  /// Constructor with data initialization
114 
115  /// Virtual destructor
116  virtual ~CacheData() { }
117 
118  /// Data accessor
119 
120  /// \return A const reference to the data
121  const madness::Future<valueT>& value() const { return value_; }
122 
123  private:
124 
125  /// Typeid accessor of the derived class
126 
127  /// \return The std::type_info of the derived class
128  virtual const std::type_info& get_type_info() const {
129  return typeid(CacheData<valueT>);
130  }
131 
132  }; // class CacheData
133 
134  public:
135 
136  /// Set the cache value accosted with \c key
137 
138  /// This will set the value associated with \c key to \c value. If
139  /// the cache element does not exist, it is inserted into the cache.
140  /// Otherwise, it is removed from the cache.
141  /// \tparam valueT The object type that will be used to set the
142  /// cache (may be a \c madness::Future type).
143  /// \param key The key associated with \c value
144  /// \param value The data that will be cached
145  template <typename valueT>
146  static void set_cache_value(const keyT& key, const valueT& value) {
147  typedef typename madness::remove_future<valueT>::type value_type;
148 
149  // Retrieve the cached future
150  typename cache_container::accessor acc;
151  if(caches_.insert(acc, datum_type(key, static_cast<Cache*>(nullptr)))) {
152 
153  // A new element was inserted, so create a new cache object.
154  acc->second = new CacheData<value_type>(value);
155  acc.release();
156 
157  } else {
158 
159  // The element already existed, so retrieve the data
160  Cache* cache = acc->second;
161  caches_.erase(acc);
162 
163  // Set the cache value
165  cache->template get<value_type>();
166  MADNESS_ASSERT(! f.probe());
167  f.set(value);
168 
169  // Cleanup cache
170  delete cache;
171  }
172  }
173 
174  /// Get the cache value accosted with \c key
175 
176  /// This will get the value associated with \c key to \c value. The
177  /// value is given in the form of a \c Future, which is set by a
178  /// call to \c set_cache_value. If the cache element does not exist,
179  /// it is inserted into the cache. Otherwise, it is removed from the
180  /// cache.
181  /// \tparam valueT The object type that will be used to set the cache
182  /// \param[in] key The key associated with \c value
183  /// \param[out] value The data that will be cached
184  template <typename valueT>
185  static void get_cache_value(const keyT& key, madness::Future<valueT>& value) {
186  // Retrieve the cached future
187  typename cache_container::accessor acc;
188  if(caches_.insert(acc, datum_type(key, static_cast<Cache*>(nullptr)))) {
189  // A new element was inserted, so create a new cache object.
190  acc->second = new CacheData<valueT>(value);
191  acc.release();
192  } else {
193  // The element already existed, so retrieve the data and
194  // remove the cache element.
195  Cache* cache = acc->second;
196  caches_.erase(acc);
197 
198  // Get the result
199  value.set(cache->template get<valueT>());
200  delete cache;
201  }
202  }
203 
204  /// Get the cache value accosted with \c key
205 
206  /// This will get the value associated with \c key to \c value. If
207  /// the cache element does not exist, it is inserted into the cache.
208  /// Otherwise, it is removed from the cache.
209  /// \tparam valueT The object type that will be used to set the cache
210  /// \param[in] key The key associated with \c value
211  /// \return A \c Future that holds/will hold the cache value, which
212  /// will be set by a call to \c set_cache_value.
213  template <typename valueT>
214  static madness::Future<valueT> get_cache_value(const keyT& key) {
215  // Retrieve the cached future
216  typename cache_container::accessor acc;
217  if(caches_.insert(acc, datum_type(key, static_cast<Cache*>(nullptr)))) {
218  // A new element was inserted, so create a new cache object.
219  acc->second = new CacheData<valueT>();
220  madness::Future<valueT> value(acc->second->template get<valueT>());
221  acc.release();
222 
223  return value;
224  } else {
225  // The element already existed, so retrieve the data and
226  // remove the cache element.
227  Cache* cache = acc->second;
228  caches_.erase(acc);
229 
230  // Get the result
231  madness::Future<valueT> value(cache->template get<valueT>());
232  delete cache;
233 
234  return value;
235  }
236  }
237 
238  }; // class DistCache
239 
240  template <typename keyT>
242 
243  } // namespace detail
244 } // namespace madness
245 
246 #endif // MADNESS_WORLD_DIST_CACHE_H__INCLUDED
Definition: worldhashmap.h:396
std::pair< iterator, bool > insert(const datumT &datum)
Definition: worldhashmap.h:468
void erase(const iterator &it)
Definition: worldhashmap.h:507
std::pair< const keyT, valueT > datumT
Definition: worldhashmap.h:399
void set(const Future< T > &other)
A.set(B), where A and B are futures ensures A has/will have the same value as B.
Definition: future.h:508
Definition: worldhashmap.h:330
void release()
Definition: worldhashmap.h:380
Cache value container.
Definition: dist_cache.h:100
virtual const std::type_info & get_type_info() const
Typeid accessor of the derived class.
Definition: dist_cache.h:128
CacheData(const madness::Future< valueT > &value)
Constructor with future initialization.
Definition: dist_cache.h:110
const madness::Future< valueT > & value() const
Data accessor.
Definition: dist_cache.h:121
virtual ~CacheData()
Virtual destructor.
Definition: dist_cache.h:116
madness::Future< valueT > value_
Local cached data.
Definition: dist_cache.h:102
CacheData()
Default constructor.
Definition: dist_cache.h:107
CacheData(const valueT &value)
Constructor with data initialization.
Definition: dist_cache.h:113
Cache interface class.
Definition: dist_cache.h:71
virtual const std::type_info & get_type_info() const =0
Typeid accessor of the derived class.
virtual ~Cache()
Virtual destructor.
Definition: dist_cache.h:75
const madness::Future< valueT > & get() const
Cache data accessor.
Definition: dist_cache.h:82
Distributed caching utility.
Definition: dist_cache.h:54
static void get_cache_value(const keyT &key, madness::Future< valueT > &value)
Get the cache value accosted with key.
Definition: dist_cache.h:185
static cache_container caches_
Cache container.
Definition: dist_cache.h:66
static void set_cache_value(const keyT &key, const valueT &value)
Set the cache value accosted with key.
Definition: dist_cache.h:146
static madness::Future< valueT > get_cache_value(const keyT &key)
Get the cache value accosted with key.
Definition: dist_cache.h:214
madness::ConcurrentHashMap< keyT, Cache * > cache_container
The container that holds cache values.
Definition: dist_cache.h:59
cache_container::datumT datum_type
Cache container datum type.
Definition: dist_cache.h:63
Implements Future and related items.
Defines madness::MadnessException for exception handling.
#define MADNESS_ASSERT(condition)
Assert a condition that should be free of side-effects since in release builds this might be a no-op.
Definition: madness_exception.h:134
File holds all helper structures necessary for the CC_Operator and CC2 class.
Definition: DFParameters.h:10
static class madness::twoscale_cache_class cache[kmax+1]
NDIM & f
Definition: mra.h:2416
T type
Type with Future removed.
Definition: type_traits.h:110
std::pair< int, double > valueT
Definition: test_binsorter.cc:6
Defines and implements a concurrent hashmap.