18bf80f4bSopenharmony_ci/* 28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License. 58bf80f4bSopenharmony_ci * You may obtain a copy of the License at 68bf80f4bSopenharmony_ci * 78bf80f4bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88bf80f4bSopenharmony_ci * 98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and 138bf80f4bSopenharmony_ci * limitations under the License. 148bf80f4bSopenharmony_ci */ 158bf80f4bSopenharmony_ci 168bf80f4bSopenharmony_ci#ifndef META_BASE_CAPTURE_HEADER 178bf80f4bSopenharmony_ci#define META_BASE_CAPTURE_HEADER 188bf80f4bSopenharmony_ci 198bf80f4bSopenharmony_ci#include <meta/base/namespace.h> 208bf80f4bSopenharmony_ci#include <meta/base/shared_ptr.h> 218bf80f4bSopenharmony_ci 228bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE() 238bf80f4bSopenharmony_ci 248bf80f4bSopenharmony_cinamespace Details { 258bf80f4bSopenharmony_ci 268bf80f4bSopenharmony_ci/** 278bf80f4bSopenharmony_ci * @brief Generic capture conversion. 288bf80f4bSopenharmony_ci */ 298bf80f4bSopenharmony_citemplate<typename Type> 308bf80f4bSopenharmony_ciType&& CaptureWrap(Type&& obj) 318bf80f4bSopenharmony_ci{ 328bf80f4bSopenharmony_ci return BASE_NS::forward<Type>(obj); 338bf80f4bSopenharmony_ci} 348bf80f4bSopenharmony_ci 358bf80f4bSopenharmony_ci/** 368bf80f4bSopenharmony_ci * @brief Helper to keep wrap type info. 378bf80f4bSopenharmony_ci */ 388bf80f4bSopenharmony_citemplate<typename T> 398bf80f4bSopenharmony_cistruct CaptureWrapper { 408bf80f4bSopenharmony_ci T value; 418bf80f4bSopenharmony_ci}; 428bf80f4bSopenharmony_ci 438bf80f4bSopenharmony_ci/** 448bf80f4bSopenharmony_ci * @brief Capture conversion for shared_ptr. 458bf80f4bSopenharmony_ci */ 468bf80f4bSopenharmony_citemplate<typename Type> 478bf80f4bSopenharmony_ciCaptureWrapper<BASE_NS::weak_ptr<Type>> CaptureWrap(BASE_NS::shared_ptr<Type> p) 488bf80f4bSopenharmony_ci{ 498bf80f4bSopenharmony_ci return { p }; 508bf80f4bSopenharmony_ci} 518bf80f4bSopenharmony_ci 528bf80f4bSopenharmony_ci/** 538bf80f4bSopenharmony_ci * @brief Capture conversion for weak_ptr. 548bf80f4bSopenharmony_ci */ 558bf80f4bSopenharmony_citemplate<typename Type> 568bf80f4bSopenharmony_ciCaptureWrapper<BASE_NS::weak_ptr<Type>> CaptureWrap(BASE_NS::weak_ptr<Type> p) 578bf80f4bSopenharmony_ci{ 588bf80f4bSopenharmony_ci return { BASE_NS::move(p) }; 598bf80f4bSopenharmony_ci} 608bf80f4bSopenharmony_ci 618bf80f4bSopenharmony_ci/** 628bf80f4bSopenharmony_ci * @brief Helper to keep unwrapped type info. 638bf80f4bSopenharmony_ci */ 648bf80f4bSopenharmony_citemplate<typename T> 658bf80f4bSopenharmony_cistruct CaptureUnWrapper { 668bf80f4bSopenharmony_ci T value; 678bf80f4bSopenharmony_ci bool valid { true }; 688bf80f4bSopenharmony_ci}; 698bf80f4bSopenharmony_ci 708bf80f4bSopenharmony_ci/** 718bf80f4bSopenharmony_ci * @brief Generic unwrap function that is called before the object is passed to the actual target function. 728bf80f4bSopenharmony_ci * This should be overloaded for wrapped types. 738bf80f4bSopenharmony_ci */ 748bf80f4bSopenharmony_citemplate<typename Type> 758bf80f4bSopenharmony_ciCaptureUnWrapper<Type> CaptureUnWrap(Type&& obj) 768bf80f4bSopenharmony_ci{ 778bf80f4bSopenharmony_ci return CaptureUnWrapper<Type> { BASE_NS::forward<Type>(obj) }; 788bf80f4bSopenharmony_ci} 798bf80f4bSopenharmony_ci 808bf80f4bSopenharmony_ci/** 818bf80f4bSopenharmony_ci * @brief Capture conversion for wrapped type to shared_ptr. 828bf80f4bSopenharmony_ci */ 838bf80f4bSopenharmony_citemplate<typename Type> 848bf80f4bSopenharmony_ciCaptureUnWrapper<BASE_NS::shared_ptr<Type>> CaptureUnWrap(const CaptureWrapper<BASE_NS::weak_ptr<Type>>& p) 858bf80f4bSopenharmony_ci{ 868bf80f4bSopenharmony_ci auto v = p.value.lock(); 878bf80f4bSopenharmony_ci return CaptureUnWrapper<BASE_NS::shared_ptr<Type>> { v, v != nullptr }; 888bf80f4bSopenharmony_ci} 898bf80f4bSopenharmony_ci 908bf80f4bSopenharmony_ci/** 918bf80f4bSopenharmony_ci * @brief Invokes a captured function. 928bf80f4bSopenharmony_ci * @tparam Check Decides if captured parameters should be valid before func is invoked. 938bf80f4bSopenharmony_ci */ 948bf80f4bSopenharmony_citemplate<bool Check, typename... Other> 958bf80f4bSopenharmony_cistruct CaptureCallImpl { 968bf80f4bSopenharmony_ci template<typename Func, typename... Args> 978bf80f4bSopenharmony_ci static auto Call(Func& func, Other&&... other, Args&&... args) 988bf80f4bSopenharmony_ci { 998bf80f4bSopenharmony_ci if constexpr (Check) { 1008bf80f4bSopenharmony_ci if ((false || ... || !args.valid)) { 1018bf80f4bSopenharmony_ci using type = decltype(func(args.value..., BASE_NS::forward<decltype(other)>(other)...)); 1028bf80f4bSopenharmony_ci if constexpr (BASE_NS::is_same_v<type, void>) { 1038bf80f4bSopenharmony_ci return; 1048bf80f4bSopenharmony_ci } else { 1058bf80f4bSopenharmony_ci return type {}; 1068bf80f4bSopenharmony_ci } 1078bf80f4bSopenharmony_ci } 1088bf80f4bSopenharmony_ci } 1098bf80f4bSopenharmony_ci return func(args.value..., BASE_NS::forward<decltype(other)>(other)...); 1108bf80f4bSopenharmony_ci } 1118bf80f4bSopenharmony_ci}; 1128bf80f4bSopenharmony_ci 1138bf80f4bSopenharmony_citemplate<bool Check, typename Lambda, typename... Args> 1148bf80f4bSopenharmony_ciauto CaptureImpl(Lambda func, Args&&... args) 1158bf80f4bSopenharmony_ci{ 1168bf80f4bSopenharmony_ci return [f = BASE_NS::move(func), args...](auto&&... other) { 1178bf80f4bSopenharmony_ci return CaptureCallImpl<Check, decltype(other)...>::Call( 1188bf80f4bSopenharmony_ci f, BASE_NS::forward<decltype(other)>(other)..., CaptureUnWrap(args)...); 1198bf80f4bSopenharmony_ci }; 1208bf80f4bSopenharmony_ci} 1218bf80f4bSopenharmony_ci 1228bf80f4bSopenharmony_ci} // namespace Details 1238bf80f4bSopenharmony_ci 1248bf80f4bSopenharmony_ci/** 1258bf80f4bSopenharmony_ci * @brief Replaces all shared pointers provided as args into weak pointers to avoid extending 1268bf80f4bSopenharmony_ci * lifetime of the pointed resources. The provided func is wrapped into capture call which first 1278bf80f4bSopenharmony_ci * locks back all weak pointers created from shared pointers and then calls the func. 1288bf80f4bSopenharmony_ci * 1298bf80f4bSopenharmony_ci * @param func Callable which will be wrapped into capture call. 1308bf80f4bSopenharmony_ci * @param args Arguments list which will be passed to the func as parameters when the capture call will have place. 1318bf80f4bSopenharmony_ci * All shared pointers in it will be replaced by weak pointers. 1328bf80f4bSopenharmony_ci * @return Capture call which will not extend the lifetime of resources pointed by shared pointers provided as args. 1338bf80f4bSopenharmony_ci */ 1348bf80f4bSopenharmony_citemplate<typename Lambda, typename... Args> 1358bf80f4bSopenharmony_cidecltype(auto) Capture(Lambda func, Args&&... args) 1368bf80f4bSopenharmony_ci{ 1378bf80f4bSopenharmony_ci return Details::CaptureImpl<false>(BASE_NS::move(func), Details::CaptureWrap(BASE_NS::forward<Args>(args))...); 1388bf80f4bSopenharmony_ci} 1398bf80f4bSopenharmony_ci 1408bf80f4bSopenharmony_ci/** 1418bf80f4bSopenharmony_ci * @brief Wraps func into capture call which checks first if all shared pointers created from weak pointers points 1428bf80f4bSopenharmony_ci * to the valid resources, and if the condition is met executes the func. 1438bf80f4bSopenharmony_ci * If this condition is not met, capture call will return the default object. 1448bf80f4bSopenharmony_ci * 1458bf80f4bSopenharmony_ci * @param func Callable which will be wrapped into capture call. 1468bf80f4bSopenharmony_ci * @param args Arguments list which will be passed to the func as parameters when the capture call will have place. 1478bf80f4bSopenharmony_ci * All shared pointers in it will be replaced by weak pointers. 1488bf80f4bSopenharmony_ci * @return Capture call which will not extend the lifetime of resources pointed by shared pointers provided as args, 1498bf80f4bSopenharmony_ci * and which will validate all resources before func call will have place. 1508bf80f4bSopenharmony_ci * 1518bf80f4bSopenharmony_ci * @see Capture 1528bf80f4bSopenharmony_ci */ 1538bf80f4bSopenharmony_citemplate<typename Lambda, typename... Args> 1548bf80f4bSopenharmony_cidecltype(auto) CaptureSafe(Lambda func, Args&&... args) 1558bf80f4bSopenharmony_ci{ 1568bf80f4bSopenharmony_ci return Details::CaptureImpl<true>(BASE_NS::move(func), Details::CaptureWrap(BASE_NS::forward<Args>(args))...); 1578bf80f4bSopenharmony_ci} 1588bf80f4bSopenharmony_ci 1598bf80f4bSopenharmony_citemplate<typename Lambda, typename Ret, typename... Args> 1608bf80f4bSopenharmony_civoid AssureCaptureTypeAndNoCapture() 1618bf80f4bSopenharmony_ci{ 1628bf80f4bSopenharmony_ci using fp = Ret (*)(Args...); 1638bf80f4bSopenharmony_ci static_assert(BASE_NS::is_convertible_v<Lambda, fp>, "Type mismatch or lambda capture"); 1648bf80f4bSopenharmony_ci} 1658bf80f4bSopenharmony_ci 1668bf80f4bSopenharmony_ciMETA_END_NAMESPACE() 1678bf80f4bSopenharmony_ci 1688bf80f4bSopenharmony_ci#endif 169