1 /*
2 * Copyright (c) 2025 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 #include "bindable_sub_thread.h"
17
18 #include "hilog_tag_wrapper.h"
19 #include "native_engine/native_engine.h"
20
21 namespace OHOS {
22 namespace AbilityRuntime {
23 namespace {
24 struct HookData {
25 std::weak_ptr<BindableSubThread> instance;
26 napi_env env = nullptr;
27 };
28 } // namespace
29
~BindableSubThread()30 BindableSubThread::~BindableSubThread()
31 {
32 TAG_LOGD(AAFwkTag::CONTEXT, "destructor");
33 }
34
BindSubThreadObject(void * napiEnv,void * object)35 void BindableSubThread::BindSubThreadObject(void* napiEnv, void* object)
36 {
37 TAG_LOGD(AAFwkTag::CONTEXT, "bind sub thread object");
38 uintptr_t key = reinterpret_cast<uintptr_t>(napiEnv);
39 std::lock_guard guard(objectsMutex_);
40 auto it = objects_.find(key);
41 if (it != objects_.end()) {
42 TAG_LOGD(AAFwkTag::CONTEXT, "object has bound");
43 return;
44 }
45
46 napi_env acutalEnv = static_cast<napi_env>(napiEnv);
47 HookData* data = new (std::nothrow) HookData { weak_from_this(), acutalEnv };
48 if (data == nullptr) {
49 TAG_LOGE(AAFwkTag::CONTEXT, "data err");
50 return;
51 }
52
53 napi_status ret = napi_add_env_cleanup_hook(acutalEnv,
54 StaticRemoveSubThreadObject, data);
55 if (ret != napi_status::napi_ok) {
56 TAG_LOGE(AAFwkTag::CONTEXT, "add hook err");
57 delete data;
58 return;
59 }
60
61 std::unique_ptr<void, void (*)(void*)> obj(object,
62 [](void* ptr) {
63 TAG_LOGD(AAFwkTag::CONTEXT, "delete sub thread ptr");
64 delete static_cast<NativeReference*>(ptr);
65 });
66 objects_.emplace(key, std::move(obj));
67 }
68
GetSubThreadObject(void * napiEnv)69 void* BindableSubThread::GetSubThreadObject(void* napiEnv)
70 {
71 TAG_LOGD(AAFwkTag::CONTEXT, "get sub thread object");
72 uintptr_t key = reinterpret_cast<uintptr_t>(napiEnv);
73 std::lock_guard guard(objectsMutex_);
74 const auto& iter = objects_.find(key);
75 if (iter == objects_.end()) {
76 TAG_LOGD(AAFwkTag::CONTEXT, "not found target object");
77 return nullptr;
78 }
79 return static_cast<void*>(iter->second.get());
80 }
81
RemoveSubThreadObject(void * napiEnv)82 void BindableSubThread::RemoveSubThreadObject(void* napiEnv)
83 {
84 TAG_LOGD(AAFwkTag::CONTEXT, "remove sub thread object");
85 uintptr_t key = reinterpret_cast<uintptr_t>(napiEnv);
86 std::lock_guard guard(objectsMutex_);
87 const auto& iter = objects_.find(key);
88 if (iter == objects_.end()) {
89 TAG_LOGW(AAFwkTag::CONTEXT, "not found target object");
90 return;
91 }
92 objects_.erase(key);
93 }
94
RemoveAllObject()95 void BindableSubThread::RemoveAllObject()
96 {
97 TAG_LOGD(AAFwkTag::CONTEXT, "remove all object");
98 std::lock_guard guard(objectsMutex_);
99 objects_.clear();
100 }
101
StaticRemoveSubThreadObject(void * arg)102 void BindableSubThread::StaticRemoveSubThreadObject(void* arg)
103 {
104 TAG_LOGD(AAFwkTag::CONTEXT, "remove sub thread object");
105 HookData* data = static_cast<HookData*>(arg);
106 if (data == nullptr) {
107 return;
108 }
109
110 std::shared_ptr<BindableSubThread> instance = data->instance.lock();
111 if (instance == nullptr) {
112 TAG_LOGW(AAFwkTag::CONTEXT, "instance nullptr");
113 delete data;
114 return;
115 }
116
117 instance->RemoveSubThreadObject(data->env);
118 delete data;
119 }
120 } // namespace AbilityRuntime
121 } // namespace OHOS
122