1 /* 2 * Copyright (c) 2023 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 #ifndef NAPI_ASYNC_WORK_H 16 #define NAPI_ASYNC_WORK_H 17 18 #include <functional> 19 #include <memory> 20 #include <string> 21 #include <uv.h> 22 23 #include "napi/native_api.h" 24 #include "napi/native_common.h" 25 #include "napi/native_node_api.h" 26 #include "napi_param_utils.h" 27 28 namespace OHOS { 29 namespace DrmStandard { 30 using NapiCbInfoParser = std::function<void(size_t argc, napi_value *argv)>; 31 using NapiAsyncExecute = std::function<void(void)>; 32 using NapiAsyncComplete = std::function<void(napi_value&)>; 33 34 struct ContextBase { 35 virtual ~ContextBase(); 36 void GetCbInfo(napi_env env, napi_callback_info info, NapiCbInfoParser parse = NapiCbInfoParser(), 37 bool sync = false); 38 void SignError(int32_t code); 39 napi_env env = nullptr; 40 napi_value output = nullptr; 41 napi_status status = napi_invalid_arg; 42 std::string errMessage; 43 int32_t errCode; 44 napi_value self = nullptr; 45 void* native = nullptr; 46 std::string taskName; 47 48 private: 49 napi_deferred deferred = nullptr; 50 napi_async_work work = nullptr; 51 napi_ref callbackRef = nullptr; 52 napi_ref selfRef = nullptr; 53 54 NapiAsyncExecute execute = nullptr; 55 NapiAsyncComplete complete = nullptr; 56 std::shared_ptr<ContextBase> hold; /* cross thread data */ 57 58 static constexpr size_t ARGC_MAX = 6; 59 60 friend class NapiAsyncWork; 61 }; 62 63 struct NapiWorkData { 64 napi_env env_; 65 napi_ref cb_; 66 }; 67 68 struct AutoRef { AutoRefAutoRef69 AutoRef(napi_env env, napi_ref cb) 70 : env_(env), cb_(cb) 71 { 72 } ~AutoRefAutoRef73 ~AutoRef() 74 { 75 uv_loop_s *loop = nullptr; 76 napi_get_uv_event_loop(env_, &loop); 77 if (loop == nullptr) { 78 return; 79 } 80 81 NapiWorkData *workData = new (std::nothrow) NapiWorkData(); 82 if (workData == nullptr) { 83 return; 84 } 85 workData->env_ = env_; 86 workData->cb_ = cb_; 87 88 uv_work_t *work = new(std::nothrow) uv_work_t; 89 if (work == nullptr) { 90 delete workData; 91 workData = nullptr; 92 return; 93 } 94 work->data = (void *)workData; 95 96 int ret = uv_queue_work_with_qos(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) { 97 // Js thread 98 NapiWorkData *workData = reinterpret_cast<NapiWorkData *>(work->data); 99 napi_env env = workData->env_; 100 napi_ref cb = workData->cb_; 101 if (env != nullptr && cb != nullptr) { 102 (void)napi_delete_reference(env, cb); 103 } 104 delete workData; 105 delete work; 106 }, uv_qos_default); 107 if (ret != 0) { 108 delete work; 109 work = nullptr; 110 delete workData; 111 workData = nullptr; 112 } 113 } 114 napi_env env_; 115 napi_ref cb_; 116 }; 117 118 class NapiAsyncWork { 119 public: 120 static napi_value Enqueue(napi_env env, std::shared_ptr<ContextBase> ctxt, const std::string &name, 121 NapiAsyncExecute execute = NapiAsyncExecute(), 122 NapiAsyncComplete complete = NapiAsyncComplete()); 123 124 private: 125 enum { 126 /* AsyncCallback / Promise output result index */ 127 RESULT_ERROR = 0, 128 RESULT_DATA = 1, 129 RESULT_ALL = 2 130 }; 131 static void CommonCallbackRoutine(ContextBase *ctxt); 132 }; 133 } // namespace DrmStandard 134 } // namespace OHOS 135 #endif // NAPI_ASYNC_WORK_H