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