1 
2 /*
3  * Copyright (c) 2024 Huawei Device Co., Ltd.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
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 
17 #ifndef CORE_CORE_PROPERTY_SCOPED_HANDLE_H
18 #define CORE_CORE_PROPERTY_SCOPED_HANDLE_H
19 
20 #include <base/containers/type_traits.h>
21 #include <base/namespace.h>
22 #include <core/log.h>
23 #include <core/namespace.h>
24 #include <core/property/intf_property_handle.h>
25 
26 BASE_BEGIN_NAMESPACE()
27 template<typename CharT>
28 class basic_string_view;
29 using string_view = basic_string_view<char>;
30 BASE_END_NAMESPACE()
31 
32 CORE_BEGIN_NAMESPACE()
33 struct PropertyTypeDecl;
34 template<typename Type, bool readOnly_ = BASE_NS::is_const_v<Type>>
35 class ScopedHandle {
36 public:
37     ScopedHandle() = default;
38 
ScopedHandle(IPropertyHandle * handle)39     explicit ScopedHandle(IPropertyHandle* handle) : handle_(handle)
40     {
41         if (handle) {
42             if constexpr (readOnly_) {
43                 data_ = static_cast<Type*>(handle->RLock());
44             } else {
45                 data_ = static_cast<Type*>(handle->WLock());
46             }
47         }
48     }
49 
ScopedHandle(const IPropertyHandle * handle)50     explicit ScopedHandle(const IPropertyHandle* handle)
51     {
52         static_assert(readOnly_, "const IPropertyHandle can be used with <const Type>.");
53         if (handle) {
54             if constexpr (readOnly_) {
55                 handle_ = handle;
56                 data_ = static_cast<Type*>(handle_->RLock());
57             }
58         }
59     }
60 
ScopedHandle(ScopedHandle && other)61     ScopedHandle(ScopedHandle&& other)
62         : handle_(BASE_NS::exchange(other.handle_, nullptr)), data_(BASE_NS::exchange(other.data_, nullptr))
63     {}
64 
65     ScopedHandle& operator=(ScopedHandle&& other) noexcept
66     {
67         if (&other != this) {
68             if (handle_) {
69                 if constexpr (readOnly_) {
70                     handle_->RUnlock();
71                 } else {
72                     handle_->WUnlock();
73                 }
74             }
75             handle_ = BASE_NS::exchange(other.handle_, nullptr);
76             data_ = BASE_NS::exchange(other.data_, nullptr);
77         }
78         return *this;
79     }
80 
~ScopedHandle()81     ~ScopedHandle()
82     {
83         if (handle_) {
84             if constexpr (readOnly_) {
85                 handle_->RUnlock();
86             } else {
87                 handle_->WUnlock();
88             }
89         }
90     }
91 
92     Type* operator->() const
93     {
94         return data_;
95     }
96 
97     Type& operator*() const
98     {
99         CORE_ASSERT(data_);
100         return *data_;
101     }
102 
103     explicit operator bool() const
104     {
105         return data_;
106     }
107 
108 private:
109     template<typename T>
110     friend ScopedHandle<T> MakeScopedHandle(
111         IPropertyHandle& handle, BASE_NS::string_view propertyName, const PropertyTypeDecl& propertyType);
112     BASE_NS::conditional_t<readOnly_, const IPropertyHandle*, IPropertyHandle*> handle_ { nullptr };
113     Type* data_ { nullptr };
114 };
115 CORE_END_NAMESPACE()
116 
117 #endif // CORE_CORE_PROPERTY_SCOPED_HANDLE_H
118