1 /*
2  * Copyright (c) 2021-2024 NVIDIA Corporation
3  *
4  * Licensed under the Apache License Version 2.0 with LLVM Exceptions
5  * (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  *
8  *   https://llvm.org/LICENSE.txt
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "__execution_fwd.hpp"
19 
20 // include these after __execution_fwd.hpp
21 #include "__concepts.hpp"
22 #include "__tag_invoke.hpp"
23 
24 #include <type_traits>
25 
26 namespace stdexec
27 {
28 // operation state tag type
29 struct operation_state_t
30 {};
31 
32 /////////////////////////////////////////////////////////////////////////////
33 // [execution.op_state]
34 namespace __start
35 {
36 struct start_t
37 {
38     template <__same_as<start_t> _Self, class _OpState>
39     STDEXEC_ATTRIBUTE((always_inline))
tag_invoke(_Self,_OpState & __op)40     friend auto tag_invoke(_Self,
41                            _OpState& __op) noexcept -> decltype(__op.start())
42     {
43         static_assert(noexcept(__op.start()),
44                       "start() members must be noexcept");
45         static_assert(__same_as<decltype(__op.start()), void>,
46                       "start() members must return void");
47         __op.start();
48     }
49 
50     template <class _Op>
51         requires tag_invocable<start_t, _Op&>
52     STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__start::start_t53     void operator()(_Op& __op) const noexcept
54     {
55         static_assert(nothrow_tag_invocable<start_t, _Op&>);
56         (void)tag_invoke(start_t{}, __op);
57     }
58 };
59 } // namespace __start
60 
61 using __start::start_t;
62 inline constexpr start_t start{};
63 
64 /////////////////////////////////////////////////////////////////////////////
65 // [execution.op_state]
66 template <class _Op>
67 concept operation_state =    //
68     destructible<_Op> &&     //
69     std::is_object_v<_Op> && //
70     requires(_Op& __op) {    //
71         stdexec::start(__op);
72     };
73 } // namespace stdexec
74