forked from NVIDIA/stdexec
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathcreate.hpp
More file actions
115 lines (100 loc) · 3.77 KB
/
create.hpp
File metadata and controls
115 lines (100 loc) · 3.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
* Copyright (c) 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/__detail/__meta.hpp"
#include "../stdexec/execution.hpp"
namespace experimental::execution
{
namespace __create
{
using namespace STDEXEC;
struct __void
{
template <class _Fun>
void emplace(_Fun&& __fun) noexcept(__nothrow_callable<_Fun>)
{
static_cast<_Fun&&>(__fun)();
}
};
template <class _Receiver, class _Args>
struct __context
{
STDEXEC_ATTRIBUTE(no_unique_address) _Receiver receiver;
STDEXEC_ATTRIBUTE(no_unique_address) _Args args;
};
template <class _Receiver, class _Fun, class _Args>
struct __opstate : STDEXEC::__immovable
{
using __context_t = __context<_Receiver, _Args>;
using __result_t = __call_result_t<_Fun, __context_t&>;
using __state_t = __if_c<__std::same_as<__result_t, void>, __void, std::optional<__result_t>>;
void start() & noexcept
{
__state_.emplace(
__emplace_from{[&]() noexcept { return static_cast<_Fun&&>(__fun_)(__ctx_); }});
}
STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS
__context_t __ctx_;
STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS
_Fun __fun_;
STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS
__state_t __state_{};
};
template <class _Fun, class _Args, class... _Sigs>
struct __sender
{
using sender_concept = STDEXEC::sender_tag;
using completion_signatures = STDEXEC::completion_signatures<_Sigs...>;
template <__decays_to<__sender> _Self, receiver_of<completion_signatures> _Receiver>
requires __callable<_Fun, __context<_Receiver, _Args>&>
&& __std::constructible_from<_Fun, __copy_cvref_t<_Self, _Fun>>
&& __std::constructible_from<_Args, __copy_cvref_t<_Self, _Args>>
STDEXEC_EXPLICIT_THIS_BEGIN(auto connect)(this _Self&& __self, _Receiver __rcvr)
-> __opstate<_Receiver, _Fun, _Args>
{
static_assert(__nothrow_callable<_Fun, __context<_Receiver, _Args>&>);
return {
{},
{static_cast<_Receiver&&>(__rcvr), static_cast<_Self&&>(__self).__args_},
static_cast<_Self&&>(__self).__fun_
};
}
STDEXEC_EXPLICIT_THIS_END(connect)
_Fun __fun_;
_Args __args_;
};
template <__completion_signature... _Sigs>
struct __create_t
{
template <class _Fun, class... _Args>
requires __std::move_constructible<_Fun>
&& __std::constructible_from<__decayed_std_tuple<_Args...>, _Args...>
auto operator()(_Fun __fun, _Args&&... __args) const
-> __sender<_Fun, __decayed_std_tuple<_Args...>, _Sigs...>
{
return {static_cast<_Fun&&>(__fun), {static_cast<_Args&&>(__args)...}};
}
};
} // namespace __create
template <class... _Sigs>
extern STDEXEC::__undefined<_Sigs...> const create;
template <STDEXEC::__completion_signature... _Sigs>
inline constexpr __create::__create_t<_Sigs...> create<_Sigs...>{};
template <STDEXEC::__completion_signature... _Sigs>
inline constexpr __create::__create_t<_Sigs...>
create<STDEXEC::completion_signatures<_Sigs...>>{};
} // namespace experimental::execution
namespace exec = experimental::execution;