1 /*
2  * Copyright (c) 2021 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 FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_SAFE_ASYNC_WORK_H
17 #define FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_SAFE_ASYNC_WORK_H
18 
19 #include "native_value.h"
20 
21 #include <mutex>
22 #include <queue>
23 #include <uv.h>
24 #ifdef LINUX_PLATFORM
25 #include <condition_variable>
26 #endif
27 
28 #include "native_async_context.h"
29 
30 #if defined(ENABLE_EVENT_HANDLER)
31 namespace OHOS::AppExecFwk {
32     class EventHandler;
33 }
34 #endif
35 
36 enum class SafeAsyncCode {
37     UNKNOWN = 0,
38     SAFE_ASYNC_QUEUE_FULL,
39     SAFE_ASYNC_INVALID_ARGS,
40     SAFE_ASYNC_CLOSED,
41     SAFE_ASYNC_FAILED,
42     SAFE_ASYNC_OK,
43 };
44 
45 enum class SafeAsyncStatus {
46     UNKNOW = 0,
47     SAFE_ASYNC_STATUS_INTE,
48     SAFE_ASYNC_STATUS_CLOSING,
49     SAFE_ASYNC_STATUS_CLOSED,
50 };
51 
52 typedef struct CallbackWrapper_ {
53     std::function<void()> cb;
54 } CallbackWrapper;
55 
56 class NativeSafeAsyncWork {
57 public:
58     static void AsyncCallback(uv_async_t* asyncHandler);
59     static void CallJs(NativeEngine* engine, napi_value js_call_func, void* context, void* data);
60 
61     NativeSafeAsyncWork(NativeEngine* engine,
62                         napi_value func,
63                         napi_value asyncResource,
64                         napi_value asyncResourceName,
65                         size_t maxQueueSize,
66                         size_t threadCount,
67                         void* finalizeData,
68                         NativeFinalize finalizeCallback,
69                         void* context,
70                         NativeThreadSafeFunctionCallJs callJsCallback);
71 
72     virtual ~NativeSafeAsyncWork();
73     virtual bool Init();
74     virtual SafeAsyncCode Send(void* data, NativeThreadSafeFunctionCallMode mode);
75     virtual SafeAsyncCode Acquire();
76     virtual SafeAsyncCode Release(NativeThreadSafeFunctionReleaseMode mode);
77     virtual bool Ref();
78     virtual bool Unref();
79     virtual void* GetContext();
80     virtual napi_status PostTask(void *data, int32_t priority, bool isTail);
81     virtual napi_status SendEvent(const std::function<void()> &cb, napi_event_priority priority);
82 
83 private:
84     void ProcessAsyncHandle();
85     SafeAsyncCode CloseHandles();
86     void CleanUp();
87     bool IsSameTid();
88     bool IsMaxQueueSize();
89 
90     SafeAsyncCode ValidEngineCheck();
91 
92     NativeEngine* engine_ = nullptr;
93     uint64_t engineId_ = 0;
94     NativeReference* ref_ = nullptr;
95     size_t maxQueueSize_ = 0;
96     size_t threadCount_ = 0;
97     void* finalizeData_ = nullptr;
98     NativeFinalize finalizeCallback_ = nullptr;
99     void* context_ = nullptr;
100     NativeThreadSafeFunctionCallJs callJsCallback_ = nullptr;
101     NativeAsyncContext asyncContext_;
102     uv_async_t asyncHandler_;
103     std::mutex mutex_;
104     std::queue<void*> queue_;
105     std::condition_variable condition_;
106     SafeAsyncStatus status_ = SafeAsyncStatus::UNKNOW;
107 #if defined(ENABLE_EVENT_HANDLER)
108     std::mutex eventHandlerMutex_;
109     std::shared_ptr<OHOS::AppExecFwk::EventHandler> eventHandler_ = nullptr;
110 #endif
111 
112 #ifdef ENABLE_CONTAINER_SCOPE
113     int32_t containerScopeId_;
114 #endif
115 };
116 
117 #endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_SAFE_ASYNC_WORK_H */
118