Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <cstddef> 7 : #include <pup.h> 8 : #include <utility> 9 : 10 : #include "DataStructures/DataBox/TagTraits.hpp" 11 : #include "Utilities/Gsl.hpp" 12 : 13 : /// \cond 14 : namespace db::detail { 15 : 16 : // Used to label the different types of items in a DataBox (which are described 17 : // in detail below for each specialization of Item). 18 : enum class ItemType { Mutable, Compute, Reference, Invalid }; 19 : 20 : // A unique item in a DataBox labeled by Tag 21 : template <typename Tag, ItemType = db::is_mutable_item_tag_v<Tag> 22 : ? ItemType::Mutable 23 : : (db::is_compute_tag_v<Tag> 24 : ? ItemType::Compute 25 : : (db::is_reference_tag_v<Tag> 26 : ? ItemType::Reference 27 : : ItemType::Invalid))> 28 : class Item { 29 : static_assert( 30 : std::is_base_of_v<db::SimpleTag, Tag>, 31 : "The Tag of an Item in the Databox must be derived from db::SimpleTag"); 32 : }; 33 : 34 : // A mutable item in a DataBox 35 : // 36 : // A mutable item is an item in a DataBox that is initialized when the DataBox 37 : // is constructed using either db::create 38 : // 39 : // Its value may be fetched by calling db::get (which calls get) 40 : // 41 : // Its value may be changed by calling db::mutate (which calls mutate) 42 : template <typename Tag> 43 : class Item<Tag, ItemType::Mutable> { 44 : public: 45 : static constexpr ItemType item_type = ItemType::Mutable; 46 : 47 : using value_type = typename Tag::type; 48 : 49 : constexpr Item() = default; 50 : constexpr Item(Item const&) = default; 51 : constexpr Item(Item&&) = default; 52 : constexpr Item& operator=(Item const&) = default; 53 : constexpr Item& operator=(Item&&) = default; 54 : ~Item() = default; 55 : 56 : explicit Item(value_type value) : value_(std::move(value)) {} 57 : 58 : const value_type& get() const { return value_; } 59 : 60 : value_type& mutate() { return value_; } 61 : 62 : // NOLINTNEXTLINE(google-runtime-references) 63 : void pup(PUP::er& p) { p | value_; } 64 : 65 : private: 66 : value_type value_{}; 67 : }; 68 : 69 : // A compute item in a DataBox 70 : // 71 : // A compute item is an item in a DataBox whose value depends upon other items 72 : // in the DataBox. It is lazily evaluated (i.e. not computed until it is 73 : // retrieved) and will be reevaluated if any of the items upon which it depends 74 : // is changed. 75 : // 76 : // A compute item is default constructed when the DataBox is constructed. 77 : // 78 : // When a compute item is fetched via db::get, db::get will check whether it has 79 : // already been evaluated (by calling evaluated). If it has been evaluated, 80 : // db::get fetches its value (via get). If it has not been evaluated (either 81 : // initially or after reset has been called), db::get will call evaluate which 82 : // will compute the value using tag::function. 83 : // 84 : // When db::mutate is called on a mutable item, all compute items that depend 85 : // (directly or indirectly) on the mutated item will have their reset function 86 : // called. 87 : // 88 : // A compute item may not be directly mutated (its value only changes after one 89 : // of its dependencies changes and it is fetched again) 90 : template <typename Tag> 91 : class Item<Tag, ItemType::Compute> { 92 : public: 93 : static constexpr ItemType item_type = ItemType::Compute; 94 : 95 : using value_type = typename Tag::type; 96 : 97 : constexpr Item() = default; 98 : constexpr Item(Item const&) = default; 99 : constexpr Item(Item&&) = default; 100 : constexpr Item& operator=(Item const&) = default; 101 : constexpr Item& operator=(Item&&) = default; 102 : ~Item() = default; 103 : 104 : const value_type& get() const { return value_; } 105 : 106 : bool evaluated() const { return evaluated_; } 107 : 108 : void reset() { evaluated_ = false; } 109 : 110 : template <typename... Args> 111 : void evaluate(const Args&... args) const { 112 : Tag::function(make_not_null(&value_), args...); 113 : evaluated_ = true; 114 : } 115 : 116 : private: 117 : // NOLINTNEXTLINE(spectre-mutable) 118 : mutable value_type value_{}; 119 : // NOLINTNEXTLINE(spectre-mutable) 120 : mutable bool evaluated_{false}; 121 : }; 122 : 123 : // A reference item in the DataBox 124 : // 125 : // A reference item is an item in a DataBox used as a const reference to a 126 : // subitem of another item (called the parent item) contained in the DataBox 127 : // 128 : // Its value may be fetched via db::get (by calling Tag::get directly) 129 : // 130 : // A reference item cannot be used to mutate its value. 131 : template <typename Tag> 132 : class Item<Tag, ItemType::Reference> { 133 : public: 134 : static constexpr ItemType item_type = ItemType::Reference; 135 : 136 : constexpr Item() = default; 137 : constexpr Item(Item const&) = default; 138 : constexpr Item(Item&&) = default; 139 : constexpr Item& operator=(Item const&) = default; 140 : constexpr Item& operator=(Item&&) = default; 141 : ~Item() = default; 142 : }; 143 : } // namespace db::detail 144 : /// \endcond