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