//===----------------------------------------------------------------------===// // // Part of CUDA Experimental in CUDA C++ Core Libraries, // under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. // //===----------------------------------------------------------------------===// #pragma once #include #include #include // IWYU pragma: keep #include #include #include #include "testing.cuh" namespace { template struct checked_value_receiver { using receiver_concept = cudax_async::receiver_t; _CCCL_HOST_DEVICE checked_value_receiver(Values... values) : _values{values...} {} _CCCL_HOST_DEVICE checked_value_receiver(checked_value_receiver&& other) noexcept : _called{::cuda::std::exchange(other._called, true)} , _values{::cuda::std::move(other._values)} {} _CCCL_HOST_DEVICE ~checked_value_receiver() { CHECK(_called); } // This overload is needed to avoid an nvcc compiler bug where a variadic // pack is not visible within the scope of a lambda. _CCCL_HOST_DEVICE void set_value() && noexcept { if constexpr (!::cuda::std::is_same_v<::cuda::std::__type_list, ::cuda::std::__type_list<>>) { FAIL("expected a value completion; got no values"); } else { _called = true; } } template _CCCL_HOST_DEVICE void set_value(As... as) && noexcept { _called = true; if constexpr (::cuda::std::is_same_v<::cuda::std::__type_list, ::cuda::std::__type_list>) { ::cuda::std::__apply( [&](auto const&... vs) { CHECK(((vs == as) && ...)); }, _values); } else { FAIL("expected a value completion; got a different value"); } } template _CCCL_HOST_DEVICE void set_error(Error) && noexcept { _called = true; FAIL("expected a value completion; got an error"); } _CCCL_HOST_DEVICE void set_stopped() && noexcept { _called = true; FAIL("expected a value completion; got stopped"); } bool _called = false; ::cuda::std::__tuple _values; }; template _CCCL_DEDUCTION_GUIDE_ATTRIBUTES checked_value_receiver(Values...) -> checked_value_receiver; template struct checked_error_receiver { using receiver_concept = cudax_async::receiver_t; template _CCCL_HOST_DEVICE void set_value(As...) && noexcept { FAIL("expected an error completion; got a value"); } template _CCCL_HOST_DEVICE void set_error(Ty ty) && noexcept { if constexpr (::cuda::std::is_same_v) { if (!::cuda::std::is_same_v) { CHECK(ty == _error); } } else { FAIL("expected an error completion; got a different error"); } } _CCCL_HOST_DEVICE void set_error(cudax::execution::exception_ptr eptr) && noexcept { _CCCL_TRY { cudax::execution::rethrow_exception(eptr); } _CCCL_CATCH (Error & e) { if constexpr (cuda::std::derived_from) { CHECK(cuda::std::string_view{e.what()} == _error.what()); } else { SUCCEED(); } } _CCCL_CATCH (::std::exception & e) { #if defined(_CCCL_NO_TYPEID) INFO("expected an error completion; got a different error. what: " << e.what()); #else INFO("expected an error completion; got a different error. what: " << e.what() << ", type: " << typeid(e).name()); #endif CHECK(false); } _CCCL_CATCH_ALL { INFO("expected an error completion; got a different error"); CHECK(false); } } _CCCL_HOST_DEVICE void set_stopped() && noexcept { FAIL("expected a value completion; got stopped"); } Error _error; }; template _CCCL_DEDUCTION_GUIDE_ATTRIBUTES checked_error_receiver(Error) -> checked_error_receiver; struct checked_stopped_receiver { using receiver_concept = cudax_async::receiver_t; template _CCCL_HOST_DEVICE void set_value(As...) && noexcept { FAIL("expected a stopped completion; got a value"); } template _CCCL_HOST_DEVICE void set_error(Ty) && noexcept { FAIL("expected an stopped completion; got an error"); } _CCCL_HOST_DEVICE void set_stopped() && noexcept {} }; template struct proxy_value_receiver { using receiver_concept = cudax_async::receiver_t; template _CCCL_HOST_DEVICE void set_value(As...) && noexcept { FAIL("expected a value completion; got a different value"); } _CCCL_HOST_DEVICE void set_value(Ty value) && noexcept { _value = value; } template _CCCL_HOST_DEVICE void set_error(Error) && noexcept { FAIL("expected a value completion; got an error"); } _CCCL_HOST_DEVICE void set_stopped() && noexcept { FAIL("expected a value completion; got stopped"); } Ty& _value; }; template _CCCL_DEDUCTION_GUIDE_ATTRIBUTES proxy_value_receiver(Ty&) -> proxy_value_receiver; } // namespace