• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 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 #include "plugins/ets/runtime/interop_js/event_loop_module.h"
17 #include "runtime/coroutines/stackful_coroutine.h"
18 #include "plugins/ets/runtime/interop_js/interop_context.h"
19 #include "plugins/ets/runtime/interop_js/intrinsics_api_impl.h"
20 
21 namespace ark::ets::interop::js {
22 
23 /*static*/
GetEventLoop()24 uv_loop_t *EventLoopCallbackPoster::GetEventLoop()
25 {
26     uv_loop_t *loop = nullptr;
27 #if defined(PANDA_TARGET_OHOS)
28     [[maybe_unused]] auto nstatus = napi_get_uv_event_loop(InteropCtx::Current()->GetJSEnv(), &loop);
29     ASSERT(nstatus == napi_ok);
30 #else
31     loop = uv_default_loop();
32 #endif
33     return loop;
34 }
35 
EventLoopCallbackPoster()36 EventLoopCallbackPoster::EventLoopCallbackPoster()
37 {
38     [[maybe_unused]] auto *coro = EtsCoroutine::GetCurrent();
39     ASSERT(coro == coro->GetPandaVM()->GetCoroutineManager()->GetMainThread());
40     auto loop = GetEventLoop();
41     async_ = Runtime::GetCurrent()->GetInternalAllocator()->New<uv_async_t>();
42     callbackQueue_ = Runtime::GetCurrent()->GetInternalAllocator()->New<ThreadSafeCallbackQueue>();
43     [[maybe_unused]] auto uvstatus = uv_async_init(loop, async_, AsyncEventToExecuteCallbacks);
44     ASSERT(uvstatus == 0);
45     async_->data = callbackQueue_;
46 }
47 
~EventLoopCallbackPoster()48 EventLoopCallbackPoster::~EventLoopCallbackPoster()
49 {
50     ASSERT(async_ != nullptr);
51     PostToEventLoop([async = this->async_]() {
52         auto deleter = [](uv_handle_t *handle) {
53             auto *poster = reinterpret_cast<ThreadSafeCallbackQueue *>(handle->data);
54             Runtime::GetCurrent()->GetInternalAllocator()->Delete(poster);
55             Runtime::GetCurrent()->GetInternalAllocator()->Delete(handle);
56         };
57         uv_close(reinterpret_cast<uv_handle_t *>(async), deleter);
58     });
59 }
60 
PostImpl(WrappedCallback && callback)61 void EventLoopCallbackPoster::PostImpl(WrappedCallback &&callback)
62 {
63     ASSERT(callback != nullptr);
64     PostToEventLoop(std::move(callback));
65 }
66 
PostToEventLoop(WrappedCallback && callback)67 void EventLoopCallbackPoster::PostToEventLoop(WrappedCallback &&callback)
68 {
69     ASSERT(async_ != nullptr);
70     callbackQueue_->PushCallback(std::move(callback), async_);
71 }
72 
73 /*static*/
AsyncEventToExecuteCallbacks(uv_async_t * async)74 void EventLoopCallbackPoster::AsyncEventToExecuteCallbacks(uv_async_t *async)
75 {
76     auto *callbackQueue = reinterpret_cast<ThreadSafeCallbackQueue *>(async->data);
77     ASSERT(callbackQueue != nullptr);
78     callbackQueue->ExecuteAllCallbacks();
79 }
80 
PushCallback(WrappedCallback && callback,uv_async_t * async)81 void EventLoopCallbackPoster::ThreadSafeCallbackQueue::PushCallback(WrappedCallback &&callback, uv_async_t *async)
82 {
83     os::memory::LockHolder lh(lock_);
84     callbackQueue_.push(std::move(callback));
85     ASSERT(async != nullptr);
86     [[maybe_unused]] auto uvstatus = uv_async_send(async);
87     ASSERT(uvstatus == 0);
88 }
89 
ExecuteAllCallbacks()90 void EventLoopCallbackPoster::ThreadSafeCallbackQueue::ExecuteAllCallbacks()
91 {
92     os::memory::LockHolder lh(lock_);
93     while (!callbackQueue_.empty()) {
94         auto callback = callbackQueue_.front();
95         callback();
96         callbackQueue_.pop();
97     }
98 }
99 
CreatePoster()100 PandaUniquePtr<CallbackPoster> EventLoopCallbackPosterFactoryImpl::CreatePoster()
101 {
102     auto poster = MakePandaUnique<EventLoopCallbackPoster>();
103     ASSERT(poster != nullptr);
104     return poster;
105 }
106 
107 }  // namespace ark::ets::interop::js
108