//@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 #ifndef KOKKOS_EBO_HPP #define KOKKOS_EBO_HPP //---------------------------------------------------------------------------- #include #include //---------------------------------------------------------------------------- #include #include //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- namespace Kokkos { namespace Impl { template struct NotOnDeviceCtorDisambiguator {}; template struct NoCtorsNotOnDevice : std::false_type {}; template struct DefaultCtorNotOnDevice : std::false_type {}; template <> struct DefaultCtorNotOnDevice<> : std::true_type {}; template class CtorNotOnDevice = NoCtorsNotOnDevice> struct EBOBaseImpl; template class CtorNotOnDevice> struct EBOBaseImpl { template ::value && std::is_constructible::value && !CtorNotOnDevice::value, int> = 0> KOKKOS_FORCEINLINE_FUNCTION constexpr explicit EBOBaseImpl( Args&&...) noexcept {} template ::value && std::is_constructible::value && CtorNotOnDevice::value, long> = 0> inline constexpr explicit EBOBaseImpl(Args&&...) noexcept {} KOKKOS_DEFAULTED_FUNCTION constexpr EBOBaseImpl(EBOBaseImpl const&) = default; KOKKOS_DEFAULTED_FUNCTION constexpr EBOBaseImpl(EBOBaseImpl&&) = default; KOKKOS_DEFAULTED_FUNCTION constexpr EBOBaseImpl& operator=(EBOBaseImpl const&) = default; KOKKOS_DEFAULTED_FUNCTION constexpr EBOBaseImpl& operator=(EBOBaseImpl&&) = default; KOKKOS_DEFAULTED_FUNCTION ~EBOBaseImpl() = default; KOKKOS_INLINE_FUNCTION constexpr T& _ebo_data_member() & { return *reinterpret_cast(this); } KOKKOS_INLINE_FUNCTION constexpr T const& _ebo_data_member() const& { return *reinterpret_cast(this); } KOKKOS_INLINE_FUNCTION T volatile& _ebo_data_member() volatile& { return *reinterpret_cast(this); } KOKKOS_INLINE_FUNCTION T const volatile& _ebo_data_member() const volatile& { return *reinterpret_cast(this); } KOKKOS_INLINE_FUNCTION constexpr T&& _ebo_data_member() && { return std::move(*reinterpret_cast(this)); } }; template class CTorsNotOnDevice> struct EBOBaseImpl { T m_ebo_object; template ::value && !CTorsNotOnDevice::value && std::is_constructible::value, int> = 0> KOKKOS_FORCEINLINE_FUNCTION constexpr explicit EBOBaseImpl( Args&&... args) noexcept(noexcept(T(std::forward(args)...))) : m_ebo_object(std::forward(args)...) {} template ::value && CTorsNotOnDevice::value && std::is_constructible::value, long> = 0> inline constexpr explicit EBOBaseImpl(Args&&... args) noexcept( noexcept(T(std::forward(args)...))) : m_ebo_object(std::forward(args)...) {} // TODO @tasking @minor DSH noexcept in the right places? KOKKOS_DEFAULTED_FUNCTION constexpr EBOBaseImpl(EBOBaseImpl const&) = default; KOKKOS_DEFAULTED_FUNCTION constexpr EBOBaseImpl(EBOBaseImpl&&) noexcept = default; KOKKOS_DEFAULTED_FUNCTION constexpr EBOBaseImpl& operator=(EBOBaseImpl const&) = default; KOKKOS_DEFAULTED_FUNCTION constexpr EBOBaseImpl& operator=(EBOBaseImpl&&) = default; KOKKOS_DEFAULTED_FUNCTION ~EBOBaseImpl() = default; KOKKOS_INLINE_FUNCTION T& _ebo_data_member() & { return m_ebo_object; } KOKKOS_INLINE_FUNCTION T const& _ebo_data_member() const& { return m_ebo_object; } KOKKOS_INLINE_FUNCTION T volatile& _ebo_data_member() volatile& { return m_ebo_object; } KOKKOS_INLINE_FUNCTION T const volatile& _ebo_data_member() const volatile& { return m_ebo_object; } KOKKOS_INLINE_FUNCTION T&& _ebo_data_member() && { return m_ebo_object; } }; /** * * @tparam T */ template class CtorsNotOnDevice = NoCtorsNotOnDevice> struct StandardLayoutNoUniqueAddressMemberEmulation : EBOBaseImpl::value, CtorsNotOnDevice> { private: using ebo_base_t = EBOBaseImpl::value, CtorsNotOnDevice>; public: using ebo_base_t::ebo_base_t; KOKKOS_FORCEINLINE_FUNCTION constexpr T& no_unique_address_data_member() & { return this->ebo_base_t::_ebo_data_member(); } KOKKOS_FORCEINLINE_FUNCTION constexpr T const& no_unique_address_data_member() const& { return this->ebo_base_t::_ebo_data_member(); } KOKKOS_FORCEINLINE_FUNCTION T volatile& no_unique_address_data_member() volatile& { return this->ebo_base_t::_ebo_data_member(); } KOKKOS_FORCEINLINE_FUNCTION T const volatile& no_unique_address_data_member() const volatile& { return this->ebo_base_t::_ebo_data_member(); } KOKKOS_FORCEINLINE_FUNCTION constexpr T&& no_unique_address_data_member() && { return this->ebo_base_t::_ebo_data_member(); } }; /** * * @tparam T */ template class CtorsNotOnDevice = NoCtorsNotOnDevice> class NoUniqueAddressMemberEmulation : private StandardLayoutNoUniqueAddressMemberEmulation { private: using base_t = StandardLayoutNoUniqueAddressMemberEmulation; public: using base_t::base_t; using base_t::no_unique_address_data_member; }; template class ExecutionSpaceInstanceStorage : private NoUniqueAddressMemberEmulation { private: using base_t = NoUniqueAddressMemberEmulation; protected: constexpr explicit ExecutionSpaceInstanceStorage() : base_t() {} KOKKOS_INLINE_FUNCTION constexpr explicit ExecutionSpaceInstanceStorage( ExecutionSpace const& arg_execution_space) : base_t(arg_execution_space) {} KOKKOS_INLINE_FUNCTION constexpr explicit ExecutionSpaceInstanceStorage( ExecutionSpace&& arg_execution_space) : base_t(std::move(arg_execution_space)) {} KOKKOS_INLINE_FUNCTION ExecutionSpace& execution_space_instance() & { return this->no_unique_address_data_member(); } KOKKOS_INLINE_FUNCTION ExecutionSpace const& execution_space_instance() const& { return this->no_unique_address_data_member(); } KOKKOS_INLINE_FUNCTION ExecutionSpace&& execution_space_instance() && { return std::move(*this).no_unique_address_data_member(); } }; template class MemorySpaceInstanceStorage : private NoUniqueAddressMemberEmulation { private: using base_t = NoUniqueAddressMemberEmulation; protected: MemorySpaceInstanceStorage() : base_t() {} KOKKOS_INLINE_FUNCTION MemorySpaceInstanceStorage(MemorySpace const& arg_memory_space) : base_t(arg_memory_space) {} KOKKOS_INLINE_FUNCTION constexpr explicit MemorySpaceInstanceStorage(MemorySpace&& arg_memory_space) : base_t(arg_memory_space) {} KOKKOS_INLINE_FUNCTION MemorySpace& memory_space_instance() & { return this->no_unique_address_data_member(); } KOKKOS_INLINE_FUNCTION MemorySpace const& memory_space_instance() const& { return this->no_unique_address_data_member(); } KOKKOS_INLINE_FUNCTION MemorySpace&& memory_space_instance() && { return std::move(*this).no_unique_address_data_member(); } }; } // end namespace Impl } // end namespace Kokkos //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- #endif /* #ifndef KOKKOS_EBO_HPP */