1 /*
2  * Copyright (c) 2023 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 "__config.hpp"
19 #include "__meta.hpp"
20 
21 namespace stdexec
22 {
23 template <class _Fn, class... _Ts>
24     requires __nothrow_callable<_Fn, _Ts...>
25 struct __scope_guard;
26 
27 template <class _Fn>
28 struct __scope_guard<_Fn>
29 {
30     STDEXEC_ATTRIBUTE((no_unique_address))
31     _Fn __fn_;
32     STDEXEC_ATTRIBUTE((no_unique_address))
33     __immovable __hidden_{};
34     bool __dismissed_{false};
35 
~__scope_guardstdexec::__scope_guard36     ~__scope_guard()
37     {
38         if (!__dismissed_)
39             static_cast<_Fn&&>(__fn_)();
40     }
41 
__dismissstdexec::__scope_guard42     void __dismiss() noexcept
43     {
44         __dismissed_ = true;
45     }
46 };
47 
48 template <class _Fn, class _T0>
49 struct __scope_guard<_Fn, _T0>
50 {
51     STDEXEC_ATTRIBUTE((no_unique_address))
52     _Fn __fn_;
53     STDEXEC_ATTRIBUTE((no_unique_address))
54     _T0 __t0_;
55     STDEXEC_ATTRIBUTE((no_unique_address))
56     __immovable __hidden_{};
57 
58     bool __dismissed_{false};
59 
__dismissstdexec::__scope_guard60     void __dismiss() noexcept
61     {
62         __dismissed_ = true;
63     }
64 
~__scope_guardstdexec::__scope_guard65     ~__scope_guard()
66     {
67         if (!__dismissed_)
68             static_cast<_Fn&&>(__fn_)(static_cast<_T0&&>(__t0_));
69     }
70 };
71 
72 template <class _Fn, class _T0, class _T1>
73 struct __scope_guard<_Fn, _T0, _T1>
74 {
75     STDEXEC_ATTRIBUTE((no_unique_address))
76     _Fn __fn_;
77     STDEXEC_ATTRIBUTE((no_unique_address))
78     _T0 __t0_;
79     STDEXEC_ATTRIBUTE((no_unique_address))
80     _T1 __t1_;
81     STDEXEC_ATTRIBUTE((no_unique_address))
82     __immovable __hidden_{};
83 
84     bool __dismissed_{false};
85 
__dismissstdexec::__scope_guard86     void __dismiss() noexcept
87     {
88         __dismissed_ = true;
89     }
90 
~__scope_guardstdexec::__scope_guard91     ~__scope_guard()
92     {
93         if (!__dismissed_)
94             static_cast<_Fn&&>(
95                 __fn_)(static_cast<_T0&&>(__t0_), static_cast<_T1&&>(__t1_));
96     }
97 };
98 
99 template <class _Fn, class _T0, class _T1, class _T2>
100 struct __scope_guard<_Fn, _T0, _T1, _T2>
101 {
102     STDEXEC_ATTRIBUTE((no_unique_address))
103     _Fn __fn_;
104     STDEXEC_ATTRIBUTE((no_unique_address))
105     _T0 __t0_;
106     STDEXEC_ATTRIBUTE((no_unique_address))
107     _T1 __t1_;
108     STDEXEC_ATTRIBUTE((no_unique_address))
109     _T2 __t2_;
110     STDEXEC_ATTRIBUTE((no_unique_address))
111     __immovable __hidden_{};
112 
113     bool __dismissed_{false};
114 
__dismissstdexec::__scope_guard115     void __dismiss() noexcept
116     {
117         __dismissed_ = true;
118     }
119 
~__scope_guardstdexec::__scope_guard120     ~__scope_guard()
121     {
122         if (!__dismissed_)
123             static_cast<_Fn&&>(
124                 __fn_)(static_cast<_T0&&>(__t0_), static_cast<_T1&&>(__t1_),
125                        static_cast<_T2&&>(__t2_));
126     }
127 };
128 
129 template <class _Fn, class... _Ts>
130 __scope_guard(_Fn, _Ts...) -> __scope_guard<_Fn, _Ts...>;
131 } // namespace stdexec
132