30 #ifndef _util_container_conc_cache_h
31 #define _util_container_conc_cache_h
39 #include <boost/tuple/tuple.hpp>
40 #include <boost/tuple/tuple_comparison.hpp>
41 #include <boost/tuple/tuple_io.hpp>
42 #include <boost/utility.hpp>
43 #include <boost/type_traits.hpp>
44 #include <boost/thread/future.hpp>
45 #include <boost/utility/enable_if.hpp>
46 #include <boost/type_traits.hpp>
47 #include <boost/mpl/range_c.hpp>
48 #include <boost/mpl/if.hpp>
49 #include <boost/mpl/at.hpp>
50 #include <boost/mpl/int.hpp>
51 #include <boost/mpl/integral_c.hpp>
52 #include <boost/mpl/vector.hpp>
53 #include <boost/mpl/equal_to.hpp>
54 #include <boost/mpl/comparison.hpp>
55 #include <boost/mpl/push_front.hpp>
56 #include <boost/mpl/replace_if.hpp>
57 #include <boost/mpl/copy.hpp>
58 #include <boost/mpl/vector_c.hpp>
59 #include <boost/mpl/back_inserter.hpp>
62 #include <madness/world/worldhashmap.h>
63 #include <madness/world/future.h>
66 #include <util/misc/iterators.h>
67 #include <util/misc/meta.h>
68 #include <util/container/conc_cache_fwd.h>
75 template<
typename... key_types>
76 struct _hash<boost::tuple<key_types...>> {
78 operator()(
const boost::tuple<key_types...>& key)
const {
79 madness::hashT seed = 0;
80 hash_recursive(key, seed);
85 template<
typename H,
typename T>
86 inline typename boost::disable_if<
87 boost::is_same<T, boost::tuples::null_type>>::type
88 hash_recursive(
const boost::tuples::cons<H, T>& key_part, madness::hashT& seed)
const
90 madness::hash_combine(seed, make_hashable(key_part.get_head()));
91 hash_recursive(key_part.get_tail(), seed);
94 template<
typename H,
typename T>
95 inline typename boost::enable_if<boost::is_same<T, boost::tuples::null_type>>::type
96 hash_recursive(
const boost::tuples::cons<H, T>& key_part, madness::hashT& seed)
const
98 madness::hash_combine(seed, make_hashable(key_part.get_head()));
102 inline typename boost::enable_if<
106 make_hashable(
const T& val)
const {
111 inline typename boost::disable_if<
115 make_hashable(
const T& val)
const {
126 template<
int n_indices,
int... PermutedIndices>
128 static constexpr
int order =
sizeof...(PermutedIndices);
131 template<
int n_indices,
int idx_1,
int idx_2>
135 typename boost::mpl::replace_if<
136 typename boost::mpl::replace_if<
137 typename boost::mpl::copy<
138 boost::mpl::range_c<int, 0, n_indices>,
139 boost::mpl::back_inserter<
140 boost::mpl::vector_c<int, n_indices>
143 boost::mpl::equal_to<
145 boost::mpl::int_<idx_1>
147 boost::mpl::int_<idx_2>
149 boost::mpl::equal_to<
151 boost::mpl::int_<idx_2>
153 boost::mpl::int_<idx_1>
157 static constexpr
int first_index = idx_1;
158 static constexpr
int second_index = idx_2;
165 typename boost::mpl::copy<
166 boost::mpl::range_c<int, 0, nkeys>,
167 boost::mpl::back_inserter< boost::mpl::vector_c<int, nkeys> >
172 template<
typename... Permutations>
174 static constexpr
int n_permutations =
sizeof...(Permutations);
180 typename... key_types
188 template<
typename... Types>
using tuple_type = boost::tuple<Types...>;
201 typedef madness::ConcurrentHashMap<key_tuple, future_value, _hash<key_tuple>>
future_map;
218 const std::function<
value_type()>& compute_fxn
222 key_tuple k(std::forward<key_types>(keys)...);
225 if(cached_values_.insert(a, std::make_pair(k,
future_value()))){
226 boost::promise<value_type> p;
227 p.set_value(compute_fxn());
228 a->second = p.get_future().share();
230 return a->second.get();
240 key_tuple k(std::forward<key_types>(keys)...);
243 if(cached_values_.insert(a, std::make_pair(k,
future_value()))){
244 boost::promise<value_type> p;
245 p.set_value(compute_fxn(k));
246 a->second = p.get_future().share();
248 return a->second.get();
254 cached_values_.clear();
272 typename... key_types
296 template <
typename val_type,
typename... key_types>
305 using super_t::ConcurrentCacheBase;
318 return this->get(keys..., compute_fxn);
325 template <
typename val_type,
int n_keys,
int idx1,
int idx2,
typename... key_types>
345 boost::is_convertible<
346 typename boost::mpl::at_c<boost::mpl::vector<key_types...>, idx1>::type,
347 typename boost::mpl::at_c<boost::mpl::vector<key_types...>, idx2>::type
350 boost::is_convertible<
351 typename boost::mpl::at_c<boost::mpl::vector<key_types...>, idx2>::type,
352 typename boost::mpl::at_c<boost::mpl::vector<key_types...>, idx1>::type
356 typename boost::mpl::at_c<boost::mpl::vector<key_types...>, idx1>::type,
357 typename boost::mpl::at_c<boost::mpl::vector<key_types...>, idx2>::type
360 "Types must be compatible to have symmetry in ConcurrentCacheWithSymmetry"
366 const std::function<value_type(
375 key_tuple k(std::forward<key_types>(keys)...);
377 if(not (boost::tuples::get<idx1>(k) < boost::tuples::get<idx2>(k))) {
382 boost::promise<value_type> p;
386 a->second = p.get_future().share();
388 return a->second.get();
397 key_tuple k_canon = make_permuted_key_tuple(k);
402 boost::promise<value_type> p;
406 a_canon->second = p.get_future().share();
411 boost::promise<value_type> perm_p;
413 permute_fxn(a_canon->second.get(), k_canon)
415 a_perm->second = perm_p.get_future().share();
418 return a_perm->second.get();
426 make_permuted_key_tuple(
const key_tuple& orig) {
427 return make_permuted_key_tuple_recursive(
428 static_cast<typename key_tuple::inherited>(orig),
429 orig, boost::mpl::int_<0>()
433 template<
typename I,
typename H,
typename T>
434 inline typename boost::enable_if_c<
436 boost::tuples::cons<H, T>
438 make_permuted_key_tuple_recursive(
439 const boost::tuples::cons<H, T>& kpart,
440 const key_tuple& orig, I not_used
443 return boost::tuples::cons<H, T>(
444 boost::tuples::get<idx2>(orig),
445 make_permuted_key_tuple_recursive(
446 kpart.get_tail(), orig,
447 typename boost::mpl::plus<I, boost::mpl::int_<1>>::type()
452 template<
typename I,
typename H,
typename T>
453 inline typename boost::enable_if_c<
455 boost::tuples::cons<H, T>
457 make_permuted_key_tuple_recursive(
458 const boost::tuples::cons<H, T>& kpart,
459 const key_tuple& orig, I not_used
462 return boost::tuples::cons<H, T>(
463 boost::tuples::get<idx1>(orig),
464 make_permuted_key_tuple_recursive(
465 kpart.get_tail(), orig,
466 typename boost::mpl::plus<I, boost::mpl::int_<1>>::type()
471 template<
typename I,
typename H,
typename T>
472 inline typename boost::disable_if_c<
473 I::value == idx1 or I::value == idx2,
474 boost::tuples::cons<H, T>
476 make_permuted_key_tuple_recursive(
477 const boost::tuples::cons<H, T>& kpart,
478 const key_tuple& orig, I not_used
481 return boost::tuples::cons<H, T>(
483 make_permuted_key_tuple_recursive(
484 kpart.get_tail(), orig,
485 typename boost::mpl::plus<I, boost::mpl::int_<1>>::type()
491 inline const boost::tuples::null_type&
492 make_permuted_key_tuple_recursive(
493 const boost::tuples::null_type& nt,
494 const key_tuple& orig, I not_used