• 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 ARK_WEB_CPPTOC_REF_COUNTED_H_
17 #define ARK_WEB_CPPTOC_REF_COUNTED_H_
18 #pragma once
19 
20 #include "base/capi/ark_web_base_ref_counted_capi.h"
21 #include "base/cpptoc/ark_web_cpptoc_macros.h"
22 #include "base/include/ark_web_base_ref_counted.h"
23 #include "base/include/ark_web_bridge_types.h"
24 #include "base/include/ark_web_types.h"
25 
26 namespace OHOS::ArkWeb {
27 
28 template<class ClassName, class BaseName, class StructName>
29 class ArkWebCppToCRefCounted : public ArkWebBaseRefCounted {
30 public:
31     ArkWebCppToCRefCounted(const ArkWebCppToCRefCounted&) = delete;
32     ArkWebCppToCRefCounted& operator=(const ArkWebCppToCRefCounted&) = delete;
33 
34     static ArkWebRefPtr<BaseName> Get(StructName* s);
35 
36     static StructName* Invert(ArkWebRefPtr<BaseName> c);
37 
38     static ArkWebRefPtr<BaseName> Revert(StructName* s);
39 
40     StructName* GetStruct();
41 
42     void IncreRef() const;
43 
44     void DecreRef() const;
45 
46 protected:
47     ArkWebCppToCRefCounted();
48     virtual ~ArkWebCppToCRefCounted() = default;
49 
50 private:
51     struct BridgeStruct {
52         ArkWebBridgeType type_;
53         BaseName* class_;
54         ArkWebCppToCRefCounted<ClassName, BaseName, StructName>* bridge_;
55         StructName struct_;
56     };
57 
58     static BridgeStruct* GetBridgeStruct(StructName* s);
59 
60     static void StructIncreRef(ark_web_base_ref_counted_t* base);
61 
62     static void StructDecreRef(ark_web_base_ref_counted_t* base);
63 
64     ArkWebRefCount ref_count_;
65     BridgeStruct bridge_struct_;
66 
67     static inline ArkWebBridgeType kBridgeType;
68 };
69 
70 template<class ClassName, class BaseName, class StructName>
ArkWebCppToCRefCounted()71 ArkWebCppToCRefCounted<ClassName, BaseName, StructName>::ArkWebCppToCRefCounted()
72 {
73     bridge_struct_.type_ = kBridgeType;
74     bridge_struct_.bridge_ = this;
75     memset(GetStruct(), 0, sizeof(StructName));
76 
77     ark_web_base_ref_counted_t* base = reinterpret_cast<ark_web_base_ref_counted_t*>(GetStruct());
78     if (base) {
79         base->size = sizeof(StructName);
80         base->incre_ref = StructIncreRef;
81         base->decre_ref = StructDecreRef;
82     }
83 }
84 
85 template<class ClassName, class BaseName, class StructName>
Get(StructName * s)86 ArkWebRefPtr<BaseName> ArkWebCppToCRefCounted<ClassName, BaseName, StructName>::Get(StructName* s)
87 {
88     BridgeStruct* bridgeStruct = GetBridgeStruct(s);
89     if (!bridgeStruct) {
90         ARK_WEB_CPPTOC_INFO_LOG("failed to get bridge struct,bridge type is %{public}d", kBridgeType);
91         return nullptr;
92     }
93 
94     return bridgeStruct->class_;
95 }
96 
97 template<class ClassName, class BaseName, class StructName>
Invert(ArkWebRefPtr<BaseName> c)98 StructName* ArkWebCppToCRefCounted<ClassName, BaseName, StructName>::Invert(ArkWebRefPtr<BaseName> c)
99 {
100     if (!c.get()) {
101         ARK_WEB_CPPTOC_DEBUG_LOG("base class is null,bridge type is %{public}d", kBridgeType);
102         return nullptr;
103     }
104 
105     ClassName* bridge = new ClassName();
106     if (!bridge) {
107         ARK_WEB_CPPTOC_WARN_LOG("failed to new class,bridge type is %{public}d", kBridgeType);
108         return nullptr;
109     }
110     StructName* capi_struct = bridge->GetStruct();
111 
112     ARK_WEB_CPPTOC_DV_LOG("bridge type is %{public}d,this is %{public}ld,capi "
113                           "struct is %{public}ld,class is %{public}ld",
114         kBridgeType, (long)bridge, (long)capi_struct, (long)c.get());
115 
116     bridge->bridge_struct_.class_ = c.get();
117     bridge->IncreRef();
118     return capi_struct;
119 }
120 
121 template<class ClassName, class BaseName, class StructName>
Revert(StructName * s)122 ArkWebRefPtr<BaseName> ArkWebCppToCRefCounted<ClassName, BaseName, StructName>::Revert(StructName* s)
123 {
124     BridgeStruct* bridgeStruct = GetBridgeStruct(s);
125     if (!bridgeStruct) {
126         ARK_WEB_CPPTOC_DEBUG_LOG("failed to get bridge struct,bridge type is %{public}d", kBridgeType);
127         return nullptr;
128     }
129 
130     ARK_WEB_CPPTOC_DV_LOG("bridge type is %{public}d,this is %{public}ld,capi "
131                           "struct is %{public}ld",
132         kBridgeType, (long)bridgeStruct->bridge_, (long)s);
133 
134     ArkWebRefPtr<BaseName> objectPtr(bridgeStruct->class_);
135     bridgeStruct->bridge_->DecreRef();
136     return objectPtr;
137 }
138 
139 template<class ClassName, class BaseName, class StructName>
GetStruct()140 StructName* ArkWebCppToCRefCounted<ClassName, BaseName, StructName>::GetStruct()
141 {
142     return &bridge_struct_.struct_;
143 }
144 
145 template<class ClassName, class BaseName, class StructName>
146 typename ArkWebCppToCRefCounted<ClassName, BaseName, StructName>::BridgeStruct*
GetBridgeStruct(StructName * s)147 ArkWebCppToCRefCounted<ClassName, BaseName, StructName>::GetBridgeStruct(StructName* s)
148 {
149     if (!s) {
150         ARK_WEB_CPPTOC_DEBUG_LOG("capi struct is null,bridge type is %{public}d", kBridgeType);
151         return nullptr;
152     }
153 
154     BridgeStruct* bridgeStruct =
155         reinterpret_cast<BridgeStruct*>(reinterpret_cast<char*>(s) - (sizeof(BridgeStruct) - sizeof(StructName)));
156     if (bridgeStruct->type_ != kBridgeType) {
157         ARK_WEB_CPPTOC_INFO_LOG("bridge type %{public}d - %{public}d is invalid", bridgeStruct->type_, kBridgeType);
158         return nullptr;
159     }
160 
161     return bridgeStruct;
162 }
163 
164 template<class ClassName, class BaseName, class StructName>
IncreRef()165 void ArkWebCppToCRefCounted<ClassName, BaseName, StructName>::IncreRef() const
166 {
167     ARK_WEB_CPPTOC_REF_LOG("bridge type is %{public}d,ref count is %{public}d,this is %{public}ld", kBridgeType,
168         ref_count_.GetRefCount(), (long)this);
169 
170     bridge_struct_.class_->IncreRef();
171 
172     ref_count_.IncreRef();
173 }
174 
175 template<class ClassName, class BaseName, class StructName>
DecreRef()176 void ArkWebCppToCRefCounted<ClassName, BaseName, StructName>::DecreRef() const
177 {
178     ARK_WEB_CPPTOC_REF_LOG("bridge type is %{public}d,ref count is %{public}d,this is %{public}ld", kBridgeType,
179         ref_count_.GetRefCount(), (long)this);
180 
181     bridge_struct_.class_->DecreRef();
182 
183     if (ref_count_.DecreRef()) {
184         ARK_WEB_CPPTOC_DV_LOG("delete cpptoc,bridge type is %{public}d,this is %{public}ld", kBridgeType, (long)this);
185 
186         delete this;
187     }
188 }
189 
190 template<class ClassName, class BaseName, class StructName>
StructIncreRef(ark_web_base_ref_counted_t * base)191 void ARK_WEB_CALLBACK ArkWebCppToCRefCounted<ClassName, BaseName, StructName>::StructIncreRef(
192     ark_web_base_ref_counted_t* base)
193 {
194     ARK_WEB_CPPTOC_REF_LOG("bridge type is %{public}d", kBridgeType);
195 
196     BridgeStruct* bridgeStruct = GetBridgeStruct(reinterpret_cast<StructName*>(base));
197     if (!bridgeStruct) {
198         ARK_WEB_CPPTOC_INFO_LOG("failed to get bridge struct,bridge type is %{public}d", kBridgeType);
199         return;
200     }
201 
202     bridgeStruct->bridge_->IncreRef();
203 }
204 
205 template<class ClassName, class BaseName, class StructName>
StructDecreRef(ark_web_base_ref_counted_t * base)206 void ARK_WEB_CALLBACK ArkWebCppToCRefCounted<ClassName, BaseName, StructName>::StructDecreRef(
207     ark_web_base_ref_counted_t* base)
208 {
209     ARK_WEB_CPPTOC_REF_LOG("bridge type is %{public}d", kBridgeType);
210 
211     BridgeStruct* bridgeStruct = GetBridgeStruct(reinterpret_cast<StructName*>(base));
212     if (!bridgeStruct) {
213         ARK_WEB_CPPTOC_INFO_LOG("failed to get bridge struct,bridge type is %{public}d", kBridgeType);
214         return;
215     }
216 
217     bridgeStruct->bridge_->DecreRef();
218 }
219 
220 } // namespace OHOS::ArkWeb
221 
222 #endif // ARK_WEB_CPPTOC_REF_COUNTED_H_
223