1 /** 2 * Copyright (c) 2024-2025 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 PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_EVENT_LOOP_MODULE_H 17 #define PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_EVENT_LOOP_MODULE_H 18 19 #include <uv.h> 20 #include <node_api.h> 21 #include <queue> 22 23 #include "runtime/include/external_callback_poster.h" 24 #include "libpandabase/os/mutex.h" 25 #include "plugins/ets/runtime/ets_vm.h" 26 27 namespace ark { 28 class Coroutine; 29 } // namespace ark 30 31 namespace ark::ets::interop::js { 32 33 class EventLoopCallbackPoster : public CallbackPoster { 34 class ThreadSafeCallbackQueue { 35 using CallbackQueue = std::queue<WrappedCallback>; 36 37 public: 38 ThreadSafeCallbackQueue() = default; 39 NO_COPY_SEMANTIC(ThreadSafeCallbackQueue); 40 NO_MOVE_SEMANTIC(ThreadSafeCallbackQueue); 41 ~ThreadSafeCallbackQueue() = default; 42 43 void PushCallback(WrappedCallback &&callback, uv_async_t *async); 44 void ExecuteAllCallbacks(); 45 bool IsEmpty(); 46 47 private: 48 os::memory::Mutex lock_; 49 CallbackQueue callbackQueue_ GUARDED_BY(lock_); 50 }; 51 52 public: 53 static_assert(PANDA_ETS_INTEROP_JS); 54 explicit EventLoopCallbackPoster(); 55 ~EventLoopCallbackPoster() override; 56 NO_COPY_SEMANTIC(EventLoopCallbackPoster); 57 NO_MOVE_SEMANTIC(EventLoopCallbackPoster); 58 59 private: 60 void PostImpl(WrappedCallback &&callback) override; 61 62 void PostToEventLoop(WrappedCallback &&callback); 63 64 static void AsyncEventToExecuteCallbacks(uv_async_t *async); 65 66 uv_async_t *async_ = nullptr; 67 ThreadSafeCallbackQueue *callbackQueue_; 68 }; 69 70 class EventLoopCallbackPosterFactoryImpl : public CallbackPosterFactoryIface { 71 public: 72 EventLoopCallbackPosterFactoryImpl() = default; 73 ~EventLoopCallbackPosterFactoryImpl() override = default; 74 NO_COPY_SEMANTIC(EventLoopCallbackPosterFactoryImpl); 75 NO_MOVE_SEMANTIC(EventLoopCallbackPosterFactoryImpl); 76 77 /** 78 * @brief Creates callback poster to perform async work in EventLoop. 79 * NOTE: This method can only be called from threads that have napi_env (e.g. Main, Exclusive Workers). 80 */ 81 PandaUniquePtr<CallbackPoster> CreatePoster() override; 82 }; 83 84 class EventLoop { 85 public: 86 static uv_loop_t *GetEventLoop(); 87 88 static void RunEventLoop(EventLoopRunMode mode = EventLoopRunMode::RUN_DEFAULT); 89 90 static void WalkEventLoop(WalkEventLoopCallback &callback, void *args); 91 }; 92 93 } // namespace ark::ets::interop::js 94 95 #endif // PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_EVENT_LOOP_MODULE_H 96