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
|