//@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #include #include namespace { // User-defined types with a View data member template class S { V v_; public: template S(std::string label, Extents... extents) : v_(std::move(label), extents...) {} KOKKOS_DEFAULTED_FUNCTION S() = default; }; template class N { // not default constructible V v_; public: template N(std::string label, Extents... extents) : v_(std::move(label), extents...) {} }; template class H { // constructible and destructible only from on the host side V v_; public: template H(std::string label, Extents... extents) : v_(std::move(label), extents...) {} H() {} ~H() {} }; template void test_view_of_views_default() { // assigning a default-constructed view to destruct the inner objects using VoV = Kokkos::View; VoV vov("vov", 2, 3); V a("a"); V b("b"); vov(0, 0) = a; vov(1, 0) = a; vov(0, 1) = b; #ifndef KOKKOS_ENABLE_IMPL_VIEW_OF_VIEWS_DESTRUCTOR_PRECONDITION_VIOLATION_WORKAROUND vov(0, 0) = V(); vov(1, 0) = V(); vov(0, 1) = V(); #endif } template void test_view_of_views_without_initializing() { // using placement new to construct the inner objects and explicitly // calling the destructor using VoV = Kokkos::View; VoV vov(Kokkos::view_alloc("vov", Kokkos::WithoutInitializing), 2, 3); V a("a"); V b("b"); new (&vov(0, 0)) V(a); new (&vov(1, 0)) V(a); new (&vov(0, 1)) V(b); #ifndef KOKKOS_ENABLE_IMPL_VIEW_OF_VIEWS_DESTRUCTOR_PRECONDITION_VIOLATION_WORKAROUND vov(0, 0).~V(); vov(1, 0).~V(); vov(0, 1).~V(); #else // leaks memory #endif } template void test_view_of_views_sequential_host_init() { // inner views value-initialized sequentially on the host, and also // sequentially destructed on the host, without the need to cleanup using VoV = Kokkos::View; VoV vov(Kokkos::view_alloc("vov", Kokkos::SequentialHostInit), 2, 3); V a("a"); V b("b"); vov(0, 0) = a; vov(1, 0) = a; vov(0, 1) = b; } TEST(TEST_CATEGORY, view_of_views_default) { test_view_of_views_default>(); test_view_of_views_default>(); // User-defined type with View data member test_view_of_views_default>>(); } TEST(TEST_CATEGORY, view_of_views_without_initializing) { test_view_of_views_without_initializing>(); test_view_of_views_without_initializing< S>>(); test_view_of_views_without_initializing< N>>(); test_view_of_views_without_initializing< H>>(); } TEST(TEST_CATEGORY, test_view_of_views_sequential_host_init) { test_view_of_views_sequential_host_init>(); test_view_of_views_sequential_host_init< S>>(); test_view_of_views_sequential_host_init< H>>(); } } // namespace