• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025-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 "napi_ref_manager.h"
17 
18 #include "camera_log.h"
19 #include "napi/native_api.h"
20 
21 namespace OHOS {
22 namespace CameraStandard {
23 /**
24  * Create a memory-safe reference
25  * @param env The napi environment
26  * @param value The napi value
27  * @param result Output parameter, returns the created reference
28  * @return napi status code, napi_ok indicates success
29  */
CreateMemSafetyRef(napi_env env,napi_value value,napi_ref * result)30 napi_status NapiRefManager::CreateMemSafetyRef(napi_env env, napi_value value, napi_ref* result)
31 {
32     MEDIA_DEBUG_LOG("NapiRefManager::CreateMemSafetyRef enter");
33     CHECK_RETURN_RET_ELOG(
34         !result || !env, napi_status::napi_invalid_arg, "NapiRefManager::CreateMemSafetyRef env or result is nullptr ");
35     napi_status status = napi_create_reference(env, value, 1, result);
36     CHECK_RETURN_RET_ELOG(status != napi_ok, status, "NapiRefManager::CreateMemSafetyRef create ref fail");
37     std::lock_guard<std::mutex> lock(mutex_);
38     auto& pr = envToRefMap_[env];
39     auto& [mpEnv, mpRefSet] = pr;
40     mpEnv = env;
41     mpRefSet.insert(*result);
42     MEDIA_DEBUG_LOG("NapiRefManager::CreateMemSafetyRef map.size: %{public}d, set.size: %{public}d",
43         static_cast<int32_t>(envToRefMap_.size()), static_cast<int32_t>(mpRefSet.size()));
44     // Add an environment cleanup hook
45     if (mpRefSet.size() == 1) {
46         status = napi_add_env_cleanup_hook(env, NapiRefManager::CleanUpHook, &pr);
47         CHECK_PRINT_WLOG(status != napi_ok,
48             "NapiRefManager::CreateMemSafetyRef napi_add_env_cleanup_hook status: %{public}d",
49             static_cast<int32_t>(status));
50     }
51     return status;
52 }
53 
54 /**
55  * Cleanup hook function
56  * @param pPr Pointer to the pair of env and refSet
57  */
CleanUpHook(void * pPr)58 void NapiRefManager::CleanUpHook(void* pPr)
59 {
60     MEDIA_INFO_LOG("NapiRefManager::CleanUpHook CleanUpHook enter");
61     CHECK_RETURN(!pPr);
62     auto& [mpEnv, _] = *reinterpret_cast<std::pair<napi_env, std::unordered_set<napi_ref>>*>(pPr);
63     NapiRefManager::CleanUpHookImpl(mpEnv);
64 }
65 
66 /**
67  * Cleanup hook implementation function
68  * @param env The napi environment
69  */
CleanUpHookImpl(napi_env env)70 void NapiRefManager::CleanUpHookImpl(napi_env env)
71 {
72     MEDIA_INFO_LOG("NapiRefManager::CleanUpHookImpl enter");
73     CHECK_RETURN(!env);
74     std::lock_guard<std::mutex> lock(mutex_);
75     auto& [_, refSet] = envToRefMap_[env];
76     MEDIA_INFO_LOG("NapiRefManager::CleanUpHookImpl to del ref, size: %{public}d", static_cast<int32_t>(refSet.size()));
77     // Iterate through the set and delete all references
78     for (auto& ref : refSet) {
79         napi_status status = napi_delete_reference(env, ref);
80         CHECK_PRINT_WLOG(
81             status != napi_ok, "NapiRefManager::CleanUpHookImpl status: %{public}d", static_cast<int32_t>(status));
82     }
83     // Remove the environment entry from the map
84     envToRefMap_.erase(env);
85 }
86 
87 std::mutex NapiRefManager::mutex_;
88 std::unordered_map<napi_env, std::pair<napi_env, std::unordered_set<napi_ref>>> NapiRefManager::envToRefMap_;
89 } // namespace CameraStandard
90 } // namespace OHOS
91