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
|