SpECTRE Documentation Coverage Report
Current view: top level - Utilities - RuntimeCache.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 20.0 % 10 2
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <array>
       7              : #include <cstddef>
       8              : #include <mutex>
       9              : #include <optional>
      10              : #include <type_traits>
      11              : #include <utility>
      12              : 
      13              : #include "Utilities/ErrorHandling/Error.hpp"
      14              : #include "Utilities/Gsl.hpp"
      15              : #include "Utilities/StaticCache.hpp"
      16              : #include "Utilities/TypeTraits/IsInteger.hpp"
      17              : 
      18              : /// \ingroup UtilitiesGroup
      19              : /// A cache that selects and lazily initializes entries at runtime.
      20              : ///
      21              : /// Unlike `StaticCache`, this class does not instantiate the generator once for
      22              : /// every combination of indices. This reduces compile time for large caches at
      23              : /// the cost of runtime index calculation and synchronization.
      24              : ///
      25              : /// \note `RuntimeCache` is tested in `Test_StaticCache.cpp`.
      26              : template <typename Generator, typename T, typename... Ranges>
      27            1 : class RuntimeCache {
      28              :  public:
      29            0 :   explicit RuntimeCache(Generator generator)
      30              :       : generator_{std::move(generator)} {}
      31              : 
      32              :   template <typename... Args>
      33            0 :   const T& operator()(const Args... parameters) const {
      34              :     static_assert(sizeof...(parameters) == sizeof...(Ranges),
      35              :                   "Number of arguments must match number of ranges.");
      36              :     size_t array_location = 0;
      37              :     ((array_location = array_location * static_cast<size_t>(Ranges::size) +
      38              :                        index<Ranges>(parameters)),
      39              :      ...);
      40              :     std::call_once(gsl::at(initialized_, array_location), [this, array_location,
      41              :                                                            &parameters...]() {
      42              :       gsl::at(cached_objects_, array_location)
      43              :           .emplace(generator_(
      44              :               static_cast<typename Ranges::value_type>(parameters)...));
      45              :     });
      46              :     return gsl::at(cached_objects_, array_location).value();
      47              :   }
      48              : 
      49              :  private:
      50              :   template <typename Range, typename U>
      51            0 :   static size_t index(const U parameter) {
      52              :     if constexpr (std::is_enum_v<U>) {
      53              :       static_assert(
      54              :           std::is_same_v<typename Range::value_type, std::remove_cv_t<U>>,
      55              :           "Mismatched enum parameter type and cached type.");
      56              :       for (size_t i = 0; i < Range::size; ++i) {
      57              :         if (parameter == gsl::at(Range::values, i)) {
      58              :           return i;
      59              :         }
      60              :       }
      61              :       ERROR("Uncached enumeration value: " << parameter);
      62              :     } else {
      63              :       static_assert(
      64              :           tt::is_integer_v<std::remove_cv_t<U>>,
      65              :           "The parameter passed for a CacheRange must be an integer type.");
      66              :       if (UNLIKELY(
      67              :               Range::start > static_cast<decltype(Range::start)>(parameter) or
      68              :               static_cast<decltype(Range::start)>(parameter) >= Range::end)) {
      69              :         ERROR("Index out of range: " << Range::start << " <= " << parameter
      70              :                                      << " < " << Range::end);
      71              :       }
      72              :       return static_cast<size_t>(
      73              :           static_cast<typename Range::value_type>(parameter) - Range::start);
      74              :     }
      75              :   }
      76              : 
      77            0 :   static constexpr size_t number_of_entries =
      78              :       (size_t{1} * ... * static_cast<size_t>(Ranges::size));
      79            0 :   Generator generator_;
      80              :   // NOLINTNEXTLINE(spectre-mutable)
      81            0 :   mutable std::array<std::once_flag, number_of_entries> initialized_{};
      82              :   // NOLINTNEXTLINE(spectre-mutable)
      83            0 :   mutable std::array<std::optional<T>, number_of_entries> cached_objects_{};
      84              : };
      85              : 
      86              : /// \ingroup UtilitiesGroup
      87              : /// Create a RuntimeCache, inferring the cached type from the generator.
      88              : template <typename... Ranges, typename Generator>
      89            1 : auto make_runtime_cache(Generator&& generator) {
      90              :   using CachedType = std::remove_cvref_t<decltype(generator(
      91              :       std::declval<typename Ranges::value_type>()...))>;
      92              :   return RuntimeCache<std::remove_cvref_t<Generator>, CachedType, Ranges...>(
      93              :       std::forward<Generator>(generator));
      94              : }
        

Generated by: LCOV version 2.0-1