Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <charm++.h> 7 : #include <type_traits> 8 : 9 : #include "Utilities/ErrorHandling/Assert.hpp" 10 : #include "Utilities/TypeTraits/IsA.hpp" 11 : 12 : namespace Parallel { 13 : /*! 14 : * \ingroup ParallelGroup 15 : * \brief The array index used for indexing Chare Arrays, mostly an 16 : * implementation detail 17 : * 18 : * The implementation is generic and can handle custom array indices. This 19 : * replaces the generated, hard-coded Charm++ array indices with a template, 20 : * allowing a single implementation to be used for different array indices. 21 : * 22 : * \details Charm++ allocates memory for `CkArrayIndex`. The size can be 23 : * configured (in the Charm++ configuration) and defaults to the size of three 24 : * integers. We place the `Index` into this buffer using placement `new`. Then, 25 : * `CkArrayIndex::data()` can be safely reinterpreted as an `Index*`. 26 : */ 27 : template <class Index> 28 1 : struct ArrayIndex : public CkArrayIndex { 29 : static_assert(std::is_standard_layout_v<Index> and std::is_trivial_v<Index>, 30 : "The array index type must be a POD, plain-old-data"); 31 : // clang-tidy: suspicious use of sizeof 32 : static_assert(sizeof(Index) <= 3 * sizeof(int), // NOLINT 33 : "The default Charm++ CK_ARRAYINDEX_MAXLEN is 3. If you have " 34 : "changed this at Charm++ configuration time then please update " 35 : "the static_assert, otherwise your Index type is too large."); 36 : // clang-tidy: suspicious use of sizeof 37 : static_assert(sizeof(Index) % sizeof(int) == 0, // NOLINT 38 : "The Charm++ array Index type must be exactly a multiple of " 39 : "the size of an integer, but the user-provided one is not."); 40 : static_assert( 41 : alignof(Index) == alignof(decltype(index)), 42 : "Incorrect alignment of Charm++ array Index type. The " 43 : "alignment must match the alignment of the internal Charm++ type"); 44 : static_assert(not tt::is_a_v<ArrayIndex, Index>, 45 : "The Index type passed to ArrayIndex cannot be an ArrayIndex"); 46 : 47 : // Use placement new to ensure that the custom index object is placed in the 48 : // memory reserved for it in the base class 49 : // clang-tidy: mark explicit: it's a conversion constructor 50 0 : ArrayIndex(const Index& array_index) // NOLINT 51 : // clang-tidy: do not use unions 52 : : array_index_(new (index) Index(array_index)) { // NOLINT 53 : // clang-tidy: suspicious use of sizeof 54 : nInts = sizeof(array_index) / sizeof(int); // NOLINT 55 : } 56 : 57 : // clang-tidy: mark explicit: it's a conversion constructor 58 0 : ArrayIndex(const CkArrayIndex& array_index) // NOLINT 59 : : CkArrayIndex(array_index), 60 : // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) 61 : array_index_(reinterpret_cast<Index*>(CkArrayIndex::data())) { 62 : ASSERT(CkArrayIndex::nInts * sizeof(int) == sizeof(Index), 63 : "The CkArrayIndex::nInts does not match the size of the custom " 64 : "array index class."); 65 : } 66 : 67 0 : ArrayIndex(const ArrayIndex& rhs) = delete; 68 0 : ArrayIndex& operator=(const ArrayIndex& rhs) = delete; 69 : 70 0 : ArrayIndex(ArrayIndex&& /*rhs*/) = delete; 71 0 : ArrayIndex& operator=(ArrayIndex&& /*rhs*/) = delete; 72 0 : ~ArrayIndex() = default; 73 : 74 0 : const Index& get_index() const { return *array_index_; } 75 : 76 : private: 77 0 : Index* array_index_ = nullptr; 78 : }; 79 : 80 0 : using ArrayIndex1D = ArrayIndex<CkIndex1D>; 81 0 : using ArrayIndex2D = ArrayIndex<CkIndex2D>; 82 0 : using ArrayIndex3D = ArrayIndex<CkIndex3D>; 83 0 : using ArrayIndex4D = ArrayIndex<CkIndex4D>; 84 0 : using ArrayIndex5D = ArrayIndex<CkIndex5D>; 85 0 : using ArrayIndex6D = ArrayIndex<CkIndex6D>; 86 : } // namespace Parallel 87 : 88 : // These namespaces have silly names because we are subverting the charm++ 89 : // utilities that prepend "CkArrayIndex" to the name of the array index. See 90 : // comments in Parallel/Algorithms/AlgorithmArray.ci for further explanation. 91 : 92 : namespace CkArrayIndexSpectreIndex_detail { 93 : template <typename Index> 94 : using ArrayIndex = ::Parallel::ArrayIndex<Index>; 95 : } // namespace CkArrayIndexSpectreIndex_detail 96 : 97 : namespace SpectreIndex_detail { 98 : template <typename Index> 99 : using ArrayIndex = Index; 100 : } // namespace SpectreIndex_detail