CachedTempBuffer.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <utility> // IWYU pragma: keep // for std::move
8 
9 #include "DataStructures/TempBuffer.hpp"
10 #include "Utilities/Gsl.hpp"
11 #include "Utilities/TMPL.hpp"
12 #include "Utilities/TaggedTuple.hpp"
13 
14 /*!
15  * \ingroup DataStructuresGroup
16  * A temporary buffer with contents computed on demand.
17  *
18  * When an entry in the buffer is first requested, it is computed by
19  * the `Computer` class. Subsequent requests just return the cached
20  * value. The computer can itself request data from the cache to use
21  * in its computations.
22  *
23  * For the cache
24  * \snippet Test_CachedTempBuffer.cpp alias
25  * the function used to compute `Tags::Scalar2<DataType>` is
26  * \snippet Test_CachedTempBuffer.cpp compute_func
27  */
28 template <typename Computer, typename... Tags>
30  public:
31  /// Construct the buffer with the given computer. `size` is passed
32  /// to the underlying `TempBuffer` constructor.
33  CachedTempBuffer(const size_t size, Computer computer) noexcept
34  : data_(size), computer_(std::move(computer)) {}
35 
36  /// Obtain a value from the buffer, computing it if necessary.
37  template <typename Tag>
38  const typename Tag::type& get_var(Tag /*meta*/) noexcept {
39  static_assert(tmpl::list_contains_v<tmpl::list<Tags...>, Tag>,
40  "The requested tag is not available. See the template "
41  "parameters of 'CachedTempBuffer' for the computer type and "
42  "the available tags, and the template parameter of the "
43  "'get_var' function for the requested tag.");
44  // This function can't be called "get" because that interferes
45  // with the ADL needed to access data_.
46  if (not get<Computed<Tag>>(computed_flags_)) {
47  computer_(make_not_null(&get<Tag>(data_)), make_not_null(this), Tag{});
48  get<Computed<Tag>>(computed_flags_) = true;
49  }
50  return get<Tag>(data_);
51  }
52 
53  private:
54  template <typename Tag>
55  struct Computed {
56  using type = bool;
57  };
58 
59  TempBuffer<tmpl::list<Tags...>> data_;
60  tuples::TaggedTuple<Computed<Tags>...> computed_flags_{
61  ((void)Tags{}, false)...};
62  Computer computer_;
63 };
64 
65 namespace CachedTempBuffer_detail {
66 template <typename Computer, typename Tags>
67 struct CachedTempBufferFromTypelistImpl;
68 template <typename Computer, typename... Tags>
69 struct CachedTempBufferFromTypelistImpl<Computer, tmpl::list<Tags...>> {
70  using type = CachedTempBuffer<Computer, Tags...>;
71 };
72 } // namespace CachedTempBuffer_detail
73 
74 /// Instantiate a `CachedTempBuffer` from a typelist instead of a parameter pack
75 template <typename Computer, typename Tags>
76 using cached_temp_buffer_from_typelist =
77  typename CachedTempBuffer_detail::CachedTempBufferFromTypelistImpl<
78  Computer, Tags>::type;
utility
get
constexpr Tag::type & get(Variables< TagList > &v) noexcept
Return Tag::type pointing into the contiguous array.
Definition: Variables.hpp:660
CachedTempBuffer::get_var
const Tag::type & get_var(Tag) noexcept
Obtain a value from the buffer, computing it if necessary.
Definition: CachedTempBuffer.hpp:38
cstddef
CachedTempBuffer
Definition: CachedTempBuffer.hpp:29
tuples::TaggedTuple
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:271
Gsl.hpp
CachedTempBuffer::CachedTempBuffer
CachedTempBuffer(const size_t size, Computer computer) noexcept
Construct the buffer with the given computer. size is passed to the underlying TempBuffer constructor...
Definition: CachedTempBuffer.hpp:33
make_not_null
gsl::not_null< T * > make_not_null(T *ptr) noexcept
Construct a not_null from a pointer. Often this will be done as an implicit conversion,...
Definition: Gsl.hpp:880
TempBuffer
A TempBuffer holds a set of Tensor<DataType>s, where DataType is either a DataVector (or similar type...
Definition: TempBuffer.hpp:30
TMPL.hpp