From d65a1a12cdca9b0483ddafe2b3f5fa514263d818 Mon Sep 17 00:00:00 2001 From: Ivan Egorov Date: Thu, 4 Nov 2021 18:07:37 +0100 Subject: [PATCH] Make sync_wait a proper CPO. Also match piped API of sync_wait and sync_wait_r. --- include/unifex/sync_wait.hpp | 52 +++++++++----- test/sync_wait_test.cpp | 133 +++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 17 deletions(-) create mode 100644 test/sync_wait_test.cpp diff --git a/include/unifex/sync_wait.hpp b/include/unifex/sync_wait.hpp index 7a1092485..657bced88 100644 --- a/include/unifex/sync_wait.hpp +++ b/include/unifex/sync_wait.hpp @@ -140,32 +140,23 @@ std::optional _impl(Sender&& sender) { } } // namespace _sync_wait -namespace _sync_wait_cpo { +namespace _sync_wait_r_cpo { + template struct _fn { template(typename Sender) - (requires typed_sender) - auto operator()(Sender&& sender) const - -> std::optional>> { - using Result = sender_single_value_result_t>; - return _sync_wait::_impl((Sender&&) sender); + (requires sender) + decltype(auto) operator()(Sender&& sender) const { + return tag_invoke(_fn{}, (Sender &&) sender); } constexpr auto operator()() const - noexcept(is_nothrow_callable_v< - tag_t, _fn>) - -> bind_back_result_t<_fn> { + noexcept(is_nothrow_callable_v, _fn>) + -> bind_back_result_t<_fn> { return bind_back(*this); } - }; -} // namespace _sync_wait_cpo - -inline constexpr _sync_wait_cpo::_fn sync_wait {}; -namespace _sync_wait_r_cpo { - template - struct _fn { template(typename Sender) (requires sender) - decltype(auto) operator()(Sender&& sender) const { + friend decltype(auto) tag_invoke(_fn, Sender&& sender) { using Result2 = non_void_t>>; return _sync_wait::_impl((Sender&&) sender); } @@ -175,6 +166,33 @@ namespace _sync_wait_r_cpo { template inline constexpr _sync_wait_r_cpo::_fn sync_wait_r {}; +namespace _sync_wait_cpo { +struct _fn { + template(typename Sender) + (requires typed_sender) + auto operator()(Sender&& sender) const + -> std::optional>> { + return tag_invoke(_fn{}, (Sender &&) sender); + } + constexpr auto operator()() const + noexcept(is_nothrow_callable_v< + tag_t, _fn>) + -> bind_back_result_t<_fn> { + return bind_back(*this); + } + + template(typename Sender) + (requires typed_sender) + friend auto tag_invoke(_fn, Sender&& sender) + -> std::optional>> { + using Result = sender_single_value_result_t>; + return tag_invoke(tag_t>{}, (Sender&&) sender); + } +}; +} // namespace _sync_wait_cpo + +inline constexpr _sync_wait_cpo::_fn sync_wait {}; + } // namespace unifex #include diff --git a/test/sync_wait_test.cpp b/test/sync_wait_test.cpp new file mode 100644 index 000000000..f0489ebd1 --- /dev/null +++ b/test/sync_wait_test.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License Version 2.0 with LLVM Exceptions + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://llvm.org/LICENSE.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language go4verning permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace unifex; + +template +struct CpoTestSenderOp { + void start() noexcept { set_value(std::move(rec), 12); } + + R rec; +}; + +struct CpoTestSenderSyncWaitR { + template < + template + class Variant, + template + class Tuple> + using value_types = Variant>; + + template