/******************************************************************************* * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * * Copyright (C) 2012-2013 by O. Parcollet * * TRIQS is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * TRIQS. If not, see . * ******************************************************************************/ #ifndef TRIQS_ARRAYS_CACHE_H #define TRIQS_ARRAYS_CACHE_H #include "./array.hpp" #include #include namespace triqs { namespace arrays { // ----------------- the implementation class ----------------------- template class cache_impl { protected: typedef memory_layout ml_t; ml_t ml; std::c14::conditional_t::type, typename view_type_if_exists_else_type::type> keeper; bool need_copy; using CacheType = array; using exposed_view_type = std::c14::conditional_t; struct internal_data { CacheType copy; exposed_view_type view; internal_data(cache_impl const& P, ml_t ml) : copy(CacheType(P.keeper, ml)), view(copy) { #ifdef TRIQS_ARRAYS_CACHE_COPY_VERBOSE std::cerr << " Cache : copy made " << std::endl << " -- TRACE = --" << std::endl << triqs::utility::stack_trace() << std::endl; #endif } }; friend struct internal_data; mutable std::shared_ptr _id; internal_data& id() const { if (!_id) _id = std::make_shared(*this, ml); return *_id; } // avoid compiling the transformation keeper-> exposed_view_type when it does not make sense, e.g. expressions exposed_view_type view1(std::true_type) const { if (need_copy) return id().view; else return keeper; } exposed_view_type view1(std::false_type) const { return id().view; } exposed_view_type view2() const { return view1(bool_constant::value>()); } bool need_copy_dynamic(DataType const& x, std::false_type) const { return false; } bool need_copy_dynamic(DataType const& x, std::true_type) const { return (x.indexmap().get_memory_layout() != ml); } void back_update(std::true_type) {} void back_update(std::false_type) { if (need_copy) keeper = id().view; } public: cache_impl(DataType const& x, ml_t ml_ = ml_t()) : ml(ml_), keeper(x) { need_copy = (!is_amv_value_or_view_class::value) || need_copy_dynamic(x, is_amv_value_or_view_class()) || (!has_contiguous_data(x)); } ~cache_impl() { back_update(bool_constant< IsConst>()); } cache_impl(cache_impl &&) = default; cache_impl(cache_impl const&) = delete; cache_impl& operator =(cache_impl const&) = delete; cache_impl& operator =(cache_impl &&) = delete; void update() { if (need_copy && _id) id().view = keeper; } exposed_view_type view() const { return view2(); } operator exposed_view_type() const { return view2(); } }; // ---------------- Users class and factories ------------------ template using cache = cache_impl; template using const_cache = cache_impl; template const_cache make_const_cache(D const& x, memory_layout ml = memory_layout{}) { return {x, ml}; } template cache make_cache(D const& x, memory_layout ml = memory_layout{}) { return {x, ml}; } } } // namespace triqs::arrays #endif