• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 ASYNC_CALL_H
16 #define ASYNC_CALL_H
17 
18 #include <functional>
19 #include <memory>
20 #include <string>
21 
22 #include "constant.h"
23 #include "js_common.h"
24 #include "log.h"
25 #include "napi/native_api.h"
26 #include "napi_utils.h"
27 #include "uv_queue.h"
28 
29 namespace OHOS::Request {
30 class AsyncCall final {
31 public:
32     class Context {
33     public:
34         using InputAction = std::function<napi_status(size_t, napi_value *, napi_value)>;
35         using OutputAction = std::function<napi_status(napi_value *)>;
36         using ExecAction = std::function<void()>;
37         Context() = default;
~Context()38         virtual ~Context()
39         {
40             ContextNapiHolder *holder =
41                 new ContextNapiHolder{ .env = env_, .callbackRef = callbackRef_, .self = self_, .work = work_ };
42             UvQueue::Call(env_, static_cast<void *>(holder), [](uv_work_t *work, int status) {
43                 // Can ensure that the `holder` is not nullptr.
44                 ContextNapiHolder *holder = static_cast<ContextNapiHolder *>(work->data);
45                 napi_handle_scope scope = nullptr;
46                 napi_open_handle_scope(holder->env, &scope);
47                 if (scope == nullptr || holder->env == nullptr || holder->work == nullptr || holder->self == nullptr) {
48                     delete holder;
49                     delete work;
50                     return;
51                 }
52                 napi_delete_async_work(holder->env, holder->work);
53                 napi_delete_reference(holder->env, holder->self);
54                 if (holder->callbackRef != nullptr) {
55                     napi_delete_reference(holder->env, holder->callbackRef);
56                 }
57                 napi_close_handle_scope(holder->env, scope);
58                 delete holder;
59                 delete work;
60             });
61         };
SetInput(InputAction action)62         inline Context &SetInput(InputAction action)
63         {
64             input_ = std::move(action);
65             return *this;
66         }
SetOutput(OutputAction action)67         inline Context &SetOutput(OutputAction action)
68         {
69             output_ = std::move(action);
70             return *this;
71         }
SetExec(ExecAction action)72         inline Context &SetExec(ExecAction action)
73         {
74             exec_ = std::move(action);
75             return *this;
76         }
Creator()77         inline napi_value Creator()
78         {
79             ExceptionError error;
80             NapiUtils::ConvertError(innerCode_, error);
81             return NapiUtils::CreateBusinessError(env_, error.code, error.errInfo, withErrCode_);
82         }
83 
84         InputAction input_ = nullptr;
85         OutputAction output_ = nullptr;
86         ExecAction exec_ = nullptr;
87 
88         napi_env env_;
89         napi_ref callbackRef_ = nullptr;
90         napi_ref self_ = nullptr;
91         napi_deferred defer_ = nullptr;
92         napi_async_work work_ = nullptr;
93 
94         int32_t innerCode_;
95         bool withErrCode_;
96         Version version_;
97     };
98 
99     AsyncCall(napi_env env, napi_callback_info info, const std::shared_ptr<Context> &context);
100     ~AsyncCall();
101     napi_value Call(const std::shared_ptr<Context> &context, const std::string &resourceName = "AsyncCall");
102 
SetQosLevel(napi_qos_t napiQosLevel)103     inline void SetQosLevel(napi_qos_t napiQosLevel)
104     {
105         napiQosLevel_ = napiQosLevel;
106     }
107 
108 private:
109     enum { ARG_ERROR, ARG_DATA, ARG_BUTT };
110 
111     struct WorkData {
112         std::shared_ptr<Context> ctx = nullptr;
~WorkDataWorkData113         ~WorkData()
114         {
115             ctx = nullptr;
116         }
117     };
118 
119     struct ContextNapiHolder {
120         napi_env env;
121         napi_ref callbackRef;
122         napi_ref self;
123         napi_async_work work;
124     };
125     static void OnExecute(napi_env env, void *data);
126     static void OnComplete(napi_env env, napi_status status, void *data);
127     napi_qos_t napiQosLevel_ = napi_qos_default;
128 };
129 } // namespace OHOS::Request
130 #endif // ASYNC_CALL_H
131