kokkos-execution 0.0.1
Loading...
Searching...
No Matches
lifetime.hpp
Go to the documentation of this file.
1// NOLINTBEGIN
2/*
3 * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4 * Copyright (c) 2025 Robert Leahy. All rights reserved.
5 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 *
7 * Licensed under the Apache License, Version 2.0 with LLVM Exceptions (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * https://llvm.org/LICENSE.txt
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#pragma once
21
22#include <cstddef>
23#include <functional>
24#include <memory>
25#include <tuple>
26#include <type_traits>
27#include <utility>
28
30#include "enter_scopes.hpp"
31#include "invoke.hpp"
32#include "object.hpp"
33#include "stdexec/execution.hpp"
34#include "within.hpp"
35
37
39
40template <typename F, typename... Objects>
41concept function = ::STDEXEC::sender<std::invoke_result_t<F, ::exec::type_of_object_t<Objects>&...>>;
42
43template <typename SenderFactory, typename... Objects>
45 ::exec::enter_scope_sender<std::invoke_result_t<SenderFactory, ::exec::enter_scope_sender_of_object_t<Objects>...>>;
46
47struct t {
48 template <typename F, ::exec::object... Objects>
49 requires function<F, Objects...>
50 constexpr ::STDEXEC::sender auto operator()(F&& f, Objects&&... objects) const noexcept(
51 std::is_nothrow_constructible_v<std::remove_cvref_t<F>, F>
52 && (std::is_nothrow_constructible_v<std::remove_cvref_t<Objects>, Objects> && ...)) {
53 return (*this)(::exec::enter_scopes, (F&&) f, (Objects&&) objects...);
54 }
55
56 template <typename SenderFactory, typename F, ::exec::object... Objects>
57 requires sender_factory<SenderFactory, Objects...> && function<F, Objects...>
58 constexpr ::STDEXEC::sender auto
59 operator()(SenderFactory&& sender_factory, F&& f, Objects&&... objects) const noexcept(
60 std::is_nothrow_constructible_v<std::remove_cvref_t<SenderFactory>, SenderFactory>
61 && std::is_nothrow_constructible_v<std::remove_cvref_t<F>, F>
62 && (std::is_nothrow_constructible_v<std::remove_cvref_t<Objects>, Objects> && ...)) {
63 return ::STDEXEC::__sexpr{t(), std::tuple((SenderFactory&&) sender_factory, (F&&) f, (Objects&&) objects...)};
64 }
65};
66
67template <typename T>
69 union type_ {
70 char c;
71 T t;
72
73 constexpr type_() noexcept
74 : c() {
75 }
76
77 constexpr ~type_() noexcept {
78 }
79 };
80
81 type_ storage_;
82 public:
83 constexpr T* get_storage() noexcept {
84 return std::addressof(storage_.t);
85 }
86
87 constexpr T& get_object() noexcept {
88 return *std::launder(get_storage());
89 }
90};
91
92template <typename Object>
94
95template <typename... Objects>
96using storage_for_objects_t = std::tuple<storage_for_object_t<Objects>...>;
97
98template <typename Tuple, typename = std::remove_cvref_t<Tuple>>
100
101template <typename Tuple, typename SenderFactory, typename F, typename... Objects>
102class make_sender<Tuple, std::tuple<SenderFactory, F, Objects...>> {
103 static constexpr auto impl_(::STDEXEC::__copy_cvref_t<Tuple, F>&& f, storage_for_object_t<Objects>&... storage)
104 noexcept(std::is_nothrow_constructible_v<F, ::STDEXEC::__copy_cvref_t<Tuple, F>>) {
105 return [f = (::STDEXEC::__copy_cvref_t<Tuple, F>&&) f,
106 &storage...]() mutable noexcept(std::is_nothrow_invocable_v<F, ::exec::type_of_object_t<Objects>&...>) {
107 return std::invoke(std::move(f), storage.get_object()...);
108 };
109 }
110 public:
111 static constexpr bool nothrow = noexcept(::exec::within(
112 std::invoke(
113 std::declval<::STDEXEC::__copy_cvref_t<Tuple, SenderFactory>>(),
114 std::invoke(
115 std::declval<::STDEXEC::__copy_cvref_t<Tuple, Objects>>(),
116 std::declval<::exec::type_of_object_t<Objects>*>())...),
117 ::STDEXEC::just()
118 | ::exec::invoke(impl_(
119 std::declval<::STDEXEC::__copy_cvref_t<Tuple, F>>(),
120 std::declval<storage_for_object_t<Objects>&>()...))));
122
123 static constexpr ::STDEXEC::sender auto impl(Tuple&& t, storage_type& storage) noexcept(nothrow) {
124 return std::apply(
125 [&](auto&& sender_factory, auto&& f, auto&&... objects) noexcept(nothrow) {
126 return std::apply(
127 [&](auto&... storage_for_object) noexcept(nothrow) {
128 return ::exec::within(
129 std::invoke(
130 (decltype(sender_factory)&&) sender_factory,
131 std::invoke((decltype(objects)&&) objects, storage_for_object.get_storage())...),
132 ::STDEXEC::just() | ::exec::invoke(impl_((decltype(f)&&) f, storage_for_object...)));
133 },
134 storage);
135 },
136 (Tuple&&) t);
137 }
138
139 using sender_type = decltype(impl(std::declval<Tuple>(), std::declval<storage_for_objects_t<Objects...>&>()));
140};
141
142template <typename Tuple, typename Receiver>
143class state {
145 typename impl_::storage_type storage_;
146 ::STDEXEC::connect_result_t<typename impl_::sender_type, Receiver> op_;
147 public:
148 explicit constexpr state(Tuple&& t, Receiver r) noexcept(impl_::nothrow)
149 : op_(::STDEXEC::connect(impl_::impl((Tuple&&) t, storage_), (Receiver&&) r)) {
150 }
151
152 constexpr void start() & noexcept {
153 ::STDEXEC::start(op_);
154 }
155};
156
157// TODO: We should be able to get a better "message" than this
159
160class impl : public ::STDEXEC::__sexpr_defaults {
161 template <typename Self, typename... Env>
163 ::STDEXEC::completion_signatures_of_t<typename make_sender<::STDEXEC::__data_of<Self>>::sender_type, Env...>;
164 public:
165 template <typename Self, typename... Env>
166 static consteval auto __get_completion_signatures() {
167 if constexpr (::STDEXEC::__minvocable_q<completions_, Self, Env...>) {
168 return completions_<Self, Env...>{};
169 } else if constexpr (sizeof...(Env) == 0) {
170 return STDEXEC::__throw_dependent_sender_error<Self>();
171 } else {
172 return ::STDEXEC::__throw_compile_time_error<
174 ::STDEXEC::_WITH_SENDER_<Self>
175 >();
176 }
177 }
178
179 static constexpr auto __get_state = []<typename Sender, typename Receiver>(Sender&& sender, Receiver r) noexcept(
180 std::is_nothrow_constructible_v<
181 state<::STDEXEC::__data_of<Sender>, Receiver>,
182 ::STDEXEC::__data_of<Sender>,
183 Receiver
184 >) -> state<::STDEXEC::__data_of<Sender>, Receiver> {
185 auto&& [_, tuple] = (Sender&&) sender;
186 return state<decltype(tuple), Receiver>((decltype(tuple)&&) tuple, (Receiver&&) r);
187 };
188 static constexpr auto __start = [](auto& state) noexcept {
189 state.start();
190 };
191};
192
193} // namespace detail::lifetime
194
196inline constexpr lifetime_t lifetime;
197
198} // namespace experimental::execution
199
200namespace STDEXEC {
201
202template <>
203struct __sexpr_impl<::exec::lifetime_t> : ::exec::detail::lifetime::impl { };
204
205} // namespace STDEXEC
206
207// NOLINTEND
::stdexec::completion_signatures_of_t< typename make_sender<::stdexec::__data_of< Self > >::sender_type, Env... > completions_
Definition lifetime.hpp:162
static consteval auto __get_completion_signatures()
Definition lifetime.hpp:166
decltype(impl(std::declval< Tuple >(), std::declval< storage_for_objects_t< Objects... > & >())) sender_type
Definition lifetime.hpp:139
static constexpr auto impl_(::stdexec::__copy_cvref_t< Tuple, F > &&f, storage_for_object_t< Objects > &... storage) noexcept(std::is_nothrow_constructible_v< F, ::stdexec::__copy_cvref_t< Tuple, F > >)
Definition lifetime.hpp:103
static constexpr ::stdexec::sender auto impl(Tuple &&t, storage_type &storage) noexcept(nothrow)
Definition lifetime.hpp:123
constexpr state(Tuple &&t, Receiver r) noexcept(impl_::nothrow)
Definition lifetime.hpp:148
::stdexec::connect_result_t< typename impl_::sender_type, Receiver > op_
Definition lifetime.hpp:146
std::tuple< storage_for_object_t< Objects >... > storage_for_objects_t
Definition lifetime.hpp:96
storage_for_object<::exec::type_of_object_t< Object > > storage_for_object_t
Definition lifetime.hpp:93
constexpr lifetime_t lifetime
Definition lifetime.hpp:196
detail::lifetime::t lifetime_t
Definition lifetime.hpp:195
constexpr ::stdexec::sender auto operator()(SenderFactory &&sender_factory, F &&f, Objects &&... objects) const noexcept(std::is_nothrow_constructible_v< std::remove_cvref_t< SenderFactory >, SenderFactory > &&std::is_nothrow_constructible_v< std::remove_cvref_t< F >, F > &&(std::is_nothrow_constructible_v< std::remove_cvref_t< Objects >, Objects > &&...))
Definition lifetime.hpp:59
constexpr ::stdexec::sender auto operator()(F &&f, Objects &&... objects) const noexcept(std::is_nothrow_constructible_v< std::remove_cvref_t< F >, F > &&(std::is_nothrow_constructible_v< std::remove_cvref_t< Objects >, Objects > &&...))
Definition lifetime.hpp:50