blob: 4df755c2caca5351e543d75092ff3121b8122733 [file] [log] [blame]
/*
* Copyright (c) 2021-2022 NVIDIA Corporation
*
* 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 governing permissions and
* limitations under the License.
*/
#pragma once
#include "../stdexec/execution.hpp"
STDEXEC_PRAGMA_PUSH()
STDEXEC_PRAGMA_IGNORE_EDG(1302)
namespace exec
{
template <class _Tag, class _Value>
using with_t = stdexec::__env::__with<_Value, _Tag>;
namespace __envs
{
struct __with_t
{
template <class _Tag, class _Value>
auto operator()(_Tag, _Value&& __val) const
{
return stdexec::__env::__with((_Value&&)__val, _Tag());
}
};
struct __without_t
{
template <class _Env, class _Tag>
decltype(auto) operator()(_Env&& __env, _Tag) const
{
return stdexec::__env::__without((_Env&&)__env, _Tag());
}
};
// For making an environment from key/value pairs and optionally
// another environment.
struct __make_env_t
{
template <stdexec::__nothrow_move_constructible _Base,
stdexec::__nothrow_move_constructible _Env>
auto operator()(_Base&& __base, _Env&& __env) const noexcept
-> stdexec::__env::__join_t<_Env, _Base>
{
return stdexec::__env::__join((_Env&&)__env, (_Base&&)__base);
}
template <stdexec::__nothrow_move_constructible _Env>
_Env operator()(_Env&& __env) const noexcept
{
return (_Env&&)__env;
}
};
} // namespace __envs
inline constexpr __envs::__with_t with{};
inline constexpr __envs::__without_t without{};
inline constexpr __envs::__make_env_t make_env{};
template <class... _Ts>
using make_env_t = stdexec::__result_of<make_env, _Ts...>;
namespace __read_with_default
{
using namespace stdexec;
struct read_with_default_t;
template <class _Tag, class _DefaultId, class _ReceiverId>
struct __operation
{
using _Default = stdexec::__t<_DefaultId>;
using _Receiver = stdexec::__t<_ReceiverId>;
struct __t : __immovable
{
using __id = __operation;
STDEXEC_ATTRIBUTE((no_unique_address)) _Default __default_;
_Receiver __rcvr_;
friend void tag_invoke(start_t, __t& __self) noexcept
{
try
{
if constexpr (__callable<_Tag, env_of_t<_Receiver>>)
{
const auto& __env = get_env(__self.__rcvr_);
set_value(std::move(__self.__rcvr_), _Tag{}(__env));
}
else
{
set_value(std::move(__self.__rcvr_),
std::move(__self.__default_));
}
}
catch (...)
{
set_error(std::move(__self.__rcvr_), std::current_exception());
}
}
};
};
template <class _Tag, class _Default, class _Receiver>
using __operation_t = __t<__operation<_Tag, __id<_Default>, __id<_Receiver>>>;
template <class _Tag, class _Default>
struct __sender
{
using __id = __sender;
using __t = __sender;
using sender_concept = stdexec::sender_t;
STDEXEC_ATTRIBUTE((no_unique_address)) _Default __default_;
template <class _Env>
using __value_t = __minvoke<
__with_default<__mbind_back_q<__call_result_t, _Env>, _Default>, _Tag>;
template <class _Env>
using __default_t = __if_c<__callable<_Tag, _Env>, __ignore, _Default>;
template <class _Env>
using __completions_t =
completion_signatures<set_value_t(__value_t<_Env>),
set_error_t(std::exception_ptr)>;
template <__decays_to<__sender> _Self, class _Receiver>
requires receiver_of<_Receiver, __completions_t<env_of_t<_Receiver>>>
friend auto tag_invoke(connect_t, _Self&& __self, _Receiver __rcvr) //
noexcept(std::is_nothrow_move_constructible_v<_Receiver>)
-> __operation_t<_Tag, __default_t<env_of_t<_Receiver>>, _Receiver>
{
return {{}, ((_Self&&)__self).__default_, (_Receiver&&)__rcvr};
}
template <class _Env>
friend auto tag_invoke(get_completion_signatures_t, __sender, _Env&&)
-> __completions_t<_Env>
{
return {};
}
};
struct __read_with_default_t
{
template <class _Tag, class _Default>
constexpr auto operator()(_Tag, _Default&& __default) const
-> __sender<_Tag, __decay_t<_Default>>
{
return {(_Default&&)__default};
}
};
} // namespace __read_with_default
inline constexpr __read_with_default::__read_with_default_t read_with_default{};
inline constexpr stdexec::__write_::__write_t write{};
} // namespace exec
STDEXEC_PRAGMA_POP()