• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef META_BASE_CAPTURE_HEADER
17 #define META_BASE_CAPTURE_HEADER
18 
19 #include <base/containers/shared_ptr.h>
20 
21 #include <meta/base/namespace.h>
22 
META_BEGIN_NAMESPACE()23 META_BEGIN_NAMESPACE()
24 
25 namespace Details {
26 
27 /**
28  * @brief Generic capture conversion.
29  */
30 template<typename Type>
31 Type&& CaptureWrap(Type&& obj)
32 {
33     return BASE_NS::forward<Type>(obj);
34 }
35 
36 /**
37  * @brief Helper to keep wrap type info.
38  */
39 template<typename T>
40 struct CaptureWrapper {
41     T value;
42 };
43 
44 /**
45  * @brief Capture conversion for shared_ptr.
46  */
47 template<typename Type>
48 CaptureWrapper<BASE_NS::weak_ptr<Type>> CaptureWrap(BASE_NS::shared_ptr<Type> p)
49 {
50     return { p };
51 }
52 
53 /**
54  * @brief Capture conversion for weak_ptr.
55  */
56 template<typename Type>
57 CaptureWrapper<BASE_NS::weak_ptr<Type>> CaptureWrap(BASE_NS::weak_ptr<Type> p)
58 {
59     return { BASE_NS::move(p) };
60 }
61 
62 /**
63  * @brief Helper to keep unwrapped type info.
64  */
65 template<typename T>
66 struct CaptureUnWrapper {
67     T value;
68     bool valid { true };
69 };
70 
71 /**
72  * @brief Generic unwrap function that is called before the object is passed to the actual target function.
73  * This should be overloaded for wrapped types.
74  */
75 template<typename Type>
76 CaptureUnWrapper<Type> CaptureUnWrap(Type&& obj)
77 {
78     return CaptureUnWrapper<Type> { BASE_NS::forward<Type>(obj) };
79 }
80 
81 /**
82  * @brief Capture conversion for wrapped type to shared_ptr.
83  */
84 template<typename Type>
85 CaptureUnWrapper<BASE_NS::shared_ptr<Type>> CaptureUnWrap(const CaptureWrapper<BASE_NS::weak_ptr<Type>>& p)
86 {
87     auto v = p.value.lock();
88     return CaptureUnWrapper<BASE_NS::shared_ptr<Type>> { v, v != nullptr };
89 }
90 
91 /**
92  * @brief Invokes a captured function.
93  * @tparam Check Decides if captured parameters should be valid before func is invoked.
94  */
95 template<bool Check, typename... Other>
96 struct CaptureCallImpl {
97     template<typename Func, typename... Args>
98     static auto Call(Func& func, Other&&... other, Args&&... args)
99     {
100         if constexpr (Check) {
101             if ((false || ... || !args.valid)) {
102                 using type = decltype(func(args.value..., BASE_NS::forward<decltype(other)>(other)...));
103                 if constexpr (BASE_NS::is_same_v<type, void>) {
104                     return;
105                 } else {
106                     return type {};
107                 }
108             }
109         }
110         return func(args.value..., BASE_NS::forward<decltype(other)>(other)...);
111     }
112 };
113 
114 template<bool Check, typename Lambda, typename... Args>
115 auto CaptureImpl(Lambda func, Args&&... args)
116 {
117     return [f = BASE_NS::move(func), args...](auto&&... other) {
118         return CaptureCallImpl<Check, decltype(other)...>::Call(
119             f, BASE_NS::forward<decltype(other)>(other)..., CaptureUnWrap(args)...);
120     };
121 }
122 
123 } // namespace Details
124 
125 /**
126  * @brief Replaces all shared pointers provided as args into weak pointers to avoid extending
127  * lifetime of the pointed resources. The provided func is wrapped into capture call which first
128  * locks back all weak pointers created from shared pointers and then calls the func.
129  *
130  * @param func Callable which will be wrapped into capture call.
131  * @param args Arguments list which will be passed to the func as parameters when the capture call will have place.
132  *             All shared pointers in it will be replaced by weak pointers.
133  * @return Capture call which will not extend the lifetime of resources pointed by shared pointers provided as args.
134  */
135 template<typename Lambda, typename... Args>
decltype(auto)136 decltype(auto) Capture(Lambda func, Args&&... args)
137 {
138     return Details::CaptureImpl<false>(BASE_NS::move(func), Details::CaptureWrap(BASE_NS::forward<Args>(args))...);
139 }
140 
141 /**
142  * @brief Wraps func into capture call which checks first if all shared pointers created from weak pointers points
143  * to the valid resources, and if the condition is met executes the func.
144  * If this condition is not met, capture call will return the default object.
145  *
146  * @param func Callable which will be wrapped into capture call.
147  * @param args Arguments list which will be passed to the func as parameters when the capture call will have place.
148  *             All shared pointers in it will be replaced by weak pointers.
149  * @return Capture call which will not extend the lifetime of resources pointed by shared pointers provided as args,
150  * and which will validate all resources before func call will have place.
151  *
152  * @see Capture
153  */
154 template<typename Lambda, typename... Args>
decltype(auto)155 decltype(auto) CaptureSafe(Lambda func, Args&&... args)
156 {
157     return Details::CaptureImpl<true>(BASE_NS::move(func), Details::CaptureWrap(BASE_NS::forward<Args>(args))...);
158 }
159 
160 template<typename Lambda, typename Ret, typename... Args>
AssureCaptureTypeAndNoCapture()161 void AssureCaptureTypeAndNoCapture()
162 {
163     using fp = Ret (*)(Args...);
164     static_assert(BASE_NS::is_convertible_v<Lambda, fp>, "Type mismatch or lambda capture");
165 }
166 
167 META_END_NAMESPACE()
168 
169 #endif
170