1 /*
2  * Copyright (c) 2024-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 CAMERA_NAPI_AUTO_REF_H
17 #define CAMERA_NAPI_AUTO_REF_H
18 
19 #include <cstddef>
20 #include <cstdint>
21 #include <memory>
22 
23 #include "js_native_api.h"
24 #include "js_native_api_types.h"
25 #include "napi/native_api.h"
26 #include "node_api.h"
27 #include "node_api_types.h"
28 
29 namespace OHOS {
30 namespace CameraStandard {
31 struct AutoRef {
32 public:
AutoRefAutoRef33     AutoRef(napi_env env, napi_value callback, bool isOnce) : isOnce_(isOnce), env_(env)
34     {
35         (void)napi_create_reference(env_, callback, 1, &callbackRef_);
36         napi_create_string_utf8(env, "~AutoRef", NAPI_AUTO_LENGTH, &tsfnName_);
37     }
38 
AutoRefAutoRef39     AutoRef(const AutoRef& other)
40     {
41         isOnce_ = other.isOnce_;
42         env_ = other.env_;
43         callbackRef_ = other.callbackRef_;
44         tsfnName_ = other.tsfnName_;
45         if (env_ != nullptr && callbackRef_ != nullptr) {
46             (void)napi_reference_ref(env_, callbackRef_, nullptr);
47         }
48     }
49 
50     AutoRef& operator=(const AutoRef& other)
51     {
52         AutoRef tmp(other);
53         std::swap(isOnce_, tmp.isOnce_);
54         std::swap(env_, tmp.env_);
55         std::swap(callbackRef_, tmp.callbackRef_);
56         std::swap(tsfnName_, tmp.tsfnName_);
57         return *this;
58     }
59 
~AutoRefAutoRef60     ~AutoRef()
61     {
62         if (callbackRef_ == nullptr) {
63             return;
64         }
65         napi_threadsafe_function tsfn = nullptr;
66         napi_status status = napi_create_threadsafe_function(
67             env_, nullptr, nullptr, tsfnName_, 0, 1, nullptr, nullptr, nullptr,
68             [](napi_env env, napi_value js_cb, void* context, void* data) {
69                 if (data == nullptr) {
70                     return;
71                 }
72                 napi_ref callbackRef = static_cast<napi_ref>(data);
73                 (void)napi_reference_unref(env, callbackRef, nullptr);
74             },
75             &tsfn);
76         if (status != napi_ok) {
77             return;
78         }
79         napi_call_threadsafe_function(tsfn, callbackRef_, napi_tsfn_nonblocking);
80         napi_release_threadsafe_function(tsfn, napi_tsfn_release);
81     }
82 
GetCallbackFunctionAutoRef83     napi_value GetCallbackFunction()
84     {
85         if (env_ == nullptr || callbackRef_ == nullptr) {
86             return nullptr;
87         }
88         napi_value callback = nullptr;
89         if (napi_get_reference_value(env_, callbackRef_, &callback) == napi_ok) {
90             return callback;
91         }
92         return nullptr;
93     }
94 
95     bool isOnce_ = false;
96 
97 private:
98     napi_env env_ = nullptr;
99     napi_ref callbackRef_ = nullptr;
100     napi_value tsfnName_ = nullptr;
101 };
102 } // namespace CameraStandard
103 } // namespace OHOS
104 #endif