mirror of
https://github.com/openharmony/js_api_module.git
synced 2026-07-20 22:07:00 -04:00
1459ce5be1
add Timer Interface for worker execute polling operation and delay operation in the worker Without waking up the system,add timer related interfaces, setTimeout, setinterval, cleartimeout, clearinterval in worker initialize issue: https://gitee.com/openharmony/js_worker_module/issues/I51DAA Signed-off-by: y00576111 <yaojian16@huawei.com> Change-Id: I7089854c7f557c3f1d9f906854a2dad682e68400
445 lines
13 KiB
C++
445 lines
13 KiB
C++
/*
|
|
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef JS_WORKER_MODULE_WORKER_WORKER_H_
|
|
#define JS_WORKER_MODULE_WORKER_WORKER_H_
|
|
|
|
#include <list>
|
|
#include <map>
|
|
#include <mutex>
|
|
#include "base/compileruntime/js_worker_module/worker/message_queue.h"
|
|
#include "base/compileruntime/js_worker_module/helper/napi_helper.h"
|
|
#include "base/compileruntime/js_worker_module/helper/object_helper.h"
|
|
#include "base/compileruntime/js_worker_module/worker/worker_runner.h"
|
|
#include "napi/native_api.h"
|
|
#include "napi/native_node_api.h"
|
|
#include "native_engine/native_engine.h"
|
|
#include "utils/log.h"
|
|
|
|
namespace CompilerRuntime::WorkerModule {
|
|
class Worker {
|
|
public:
|
|
static const int8_t WORKERPARAMNUM = 2;
|
|
|
|
enum RunnerState { STARTING, RUNNING, TERMINATEING, TERMINATED };
|
|
enum HostState { ACTIVE, INACTIVE };
|
|
enum ListenerMode { ONCE, PERMANENT };
|
|
|
|
enum ScriptMode { CLASSIC, MODULE };
|
|
|
|
struct WorkerListener {
|
|
WorkerListener(napi_env env, napi_ref callback, ListenerMode mode)
|
|
: env_(env), callback_(callback), mode_(mode)
|
|
{}
|
|
|
|
~WorkerListener()
|
|
{
|
|
Helper::NapiHelper::DeleteReference(env_, callback_);
|
|
callback_ = nullptr;
|
|
}
|
|
|
|
bool NextIsAvailable() const
|
|
{
|
|
return mode_ != ONCE;
|
|
}
|
|
|
|
void SetMode(ListenerMode mode)
|
|
{
|
|
mode_ = mode;
|
|
}
|
|
|
|
bool operator==(const WorkerListener& listener) const;
|
|
|
|
napi_env env_ {NULL};
|
|
napi_ref callback_ {NULL};
|
|
ListenerMode mode_ {PERMANENT};
|
|
};
|
|
|
|
struct FindWorkerListener {
|
|
FindWorkerListener(napi_env env, napi_ref ref) : env_(env), ref_(ref) {}
|
|
|
|
bool operator()(const WorkerListener* listener) const
|
|
{
|
|
napi_value compareObj = Helper::NapiHelper::GetReferenceValue(env_, listener->callback_);
|
|
napi_value obj = Helper::NapiHelper::GetReferenceValue(env_, ref_);
|
|
// the env of listener and cmp listener must be same env because of Synchronization method
|
|
return Helper::NapiHelper::StrictEqual(env_, compareObj, obj);
|
|
}
|
|
|
|
napi_env env_ {nullptr};
|
|
napi_ref ref_ {nullptr};
|
|
};
|
|
|
|
/**
|
|
* Creates a worker instance.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param thisVar URL of the script to be executed by the worker.
|
|
*/
|
|
Worker(napi_env env, napi_ref thisVar);
|
|
|
|
/**
|
|
* The destructor of the Worker.
|
|
*/
|
|
~Worker();
|
|
|
|
/**
|
|
* The host thread receives the information.
|
|
*
|
|
* @param req The value of the object passed in by the js layer.
|
|
*/
|
|
static void HostOnMessage(const uv_async_t* req);
|
|
|
|
/**
|
|
* The host thread receives the information.
|
|
*
|
|
* @param req The value of the object passed in by the js layer.
|
|
*/
|
|
static void HostOnError(const uv_async_t* req);
|
|
|
|
/**
|
|
* The worker thread receives the information.
|
|
*
|
|
* @param req The value of the object passed in by the js layer.
|
|
*/
|
|
static void WorkerOnMessage(const uv_async_t* req);
|
|
|
|
/**
|
|
* ExecuteIn in thread.
|
|
*
|
|
* @param data The worker pointer.
|
|
*/
|
|
static void ExecuteInThread(const void* data);
|
|
|
|
/**
|
|
* Post a message.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param thisVar The callback information of the js layer.
|
|
*/
|
|
static napi_value PostMessage(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* Add event listeners to host.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value PostMessageToHost(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* Terminates the worker thread to stop the worker from receiving messages.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value Terminate(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* Close the worker.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value CloseWorker(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* Adds an event listener to the worker.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value On(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* Adds an event listener to the worker and removes the event listener automatically after it is invoked once.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value Once(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* Removes an event listener to the worker.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value Off(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* Add event listeners.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value AddEventListener(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* Dispatch the event.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value DispatchEvent(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* Remove the event listener.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value RemoveEventListener(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* Remove all listener.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value RemoveAllListener(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* Add the listener.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value AddListener(napi_env env, napi_callback_info cbinfo, ListenerMode mode);
|
|
|
|
/**
|
|
* Remove the listener.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value RemoveListener(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* The constructor of worker.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value WorkerConstructor(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* Initialize the worker.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value InitWorker(napi_env env, napi_value exports);
|
|
|
|
/**
|
|
* Cancel the task.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value CancelTask(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* The parent port cancels the task.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value ParentPortCancelTask(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* The parent port adds an event listener.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value ParentPortAddEventListener(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* The parent port removes all event listener.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value ParentPortRemoveAllListener(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* The parent port dispatch the event listener.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value ParentPortDispatchEvent(napi_env env, napi_callback_info cbinfo);
|
|
|
|
/**
|
|
* The parent port removes the event listener.
|
|
*
|
|
* @param env NAPI environment parameters.
|
|
* @param cbinfo The callback information of the js layer.
|
|
*/
|
|
static napi_value ParentPortRemoveEventListener(napi_env env, napi_callback_info cbinfo);
|
|
|
|
void StartExecuteInThread(napi_env env, const char* script);
|
|
|
|
bool UpdateWorkerState(RunnerState state);
|
|
bool UpdateHostState(HostState state);
|
|
|
|
bool IsRunning() const
|
|
{
|
|
return runnerState_.load(std::memory_order_acquire) == RUNNING;
|
|
}
|
|
|
|
bool IsTerminated() const
|
|
{
|
|
return runnerState_.load(std::memory_order_acquire) >= TERMINATED;
|
|
}
|
|
|
|
bool IsTerminating() const
|
|
{
|
|
return runnerState_.load(std::memory_order_acquire) == TERMINATEING;
|
|
}
|
|
|
|
void SetScriptMode(ScriptMode mode)
|
|
{
|
|
scriptMode_ = mode;
|
|
}
|
|
|
|
void AddListenerInner(napi_env env, const char* type, const WorkerListener* listener);
|
|
void RemoveListenerInner(napi_env env, const char* type, napi_ref callback);
|
|
void RemoveAllListenerInner();
|
|
|
|
uv_loop_t* GetWorkerLoop() const
|
|
{
|
|
if (workerEnv_ != nullptr) {
|
|
return Helper::NapiHelper::GetLibUV(workerEnv_);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void SetWorkerEnv(napi_env workerEnv)
|
|
{
|
|
workerEnv_ = workerEnv;
|
|
}
|
|
|
|
std::string GetScript() const
|
|
{
|
|
return script_;
|
|
}
|
|
|
|
std::string GetName() const
|
|
{
|
|
return name_;
|
|
}
|
|
|
|
bool ClearWorkerTasks()
|
|
{
|
|
if (hostEnv_ != nullptr) {
|
|
workerMessageQueue_.Clear(hostEnv_);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool HostIsStop() const
|
|
{
|
|
return hostState_.load(std::memory_order_acquire) == INACTIVE;
|
|
}
|
|
|
|
bool IsSameWorkerEnv(napi_env env) const
|
|
{
|
|
return workerEnv_ == env;
|
|
}
|
|
|
|
void Loop()
|
|
{
|
|
uv_loop_t* loop = GetWorkerLoop();
|
|
uv_run(loop, UV_RUN_DEFAULT);
|
|
}
|
|
|
|
private:
|
|
void WorkerOnMessageInner();
|
|
void HostOnMessageInner();
|
|
void HostOnErrorInner();
|
|
void HostOnMessageErrorInner();
|
|
void WorkerOnMessageErrorInner();
|
|
void WorkerOnErrorInner(napi_value error);
|
|
|
|
void HandleException();
|
|
bool CallWorkerFunction(size_t argc, const napi_value* argv, const char* methodName, bool tryCatch);
|
|
void CallHostFunction(size_t argc, const napi_value* argv, const char* methodName) const;
|
|
|
|
void HandleEventListeners(napi_env env, napi_value recv, size_t argc, const napi_value* argv, const char* type);
|
|
void ParentPortHandleEventListeners(napi_env env, napi_value recv,
|
|
size_t argc, const napi_value* argv, const char* type);
|
|
void TerminateInner();
|
|
|
|
void PostMessageInner(MessageDataType data);
|
|
void PostMessageToHostInner(MessageDataType data);
|
|
|
|
void TerminateWorker();
|
|
void CloseInner();
|
|
|
|
void PublishWorkerOverSignal();
|
|
void CloseWorkerCallback();
|
|
void CloseHostCallback() const;
|
|
|
|
void ReleaseWorkerThreadContent();
|
|
void ReleaseHostThreadContent();
|
|
bool PrepareForWorkerInstance();
|
|
void ParentPortAddListenerInner(napi_env env, const char* type, const WorkerListener* listener);
|
|
void ParentPortRemoveAllListenerInner();
|
|
void ParentPortRemoveListenerInner(napi_env env, const char* type, napi_ref callback);
|
|
void PreparePandafile();
|
|
|
|
napi_env GetHostEnv() const
|
|
{
|
|
return hostEnv_;
|
|
}
|
|
|
|
napi_env GetWorkerEnv() const
|
|
{
|
|
return workerEnv_;
|
|
}
|
|
|
|
std::string script_ {};
|
|
std::string name_ {};
|
|
ScriptMode scriptMode_ {CLASSIC};
|
|
|
|
MessageQueue workerMessageQueue_ {};
|
|
MessageQueue hostMessageQueue_ {};
|
|
MessageQueue errorQueue_ {};
|
|
|
|
uv_async_t workerOnMessageSignal_ {};
|
|
uv_async_t hostOnMessageSignal_ {};
|
|
uv_async_t hostOnErrorSignal_ {};
|
|
|
|
std::atomic<RunnerState> runnerState_ {STARTING};
|
|
std::atomic<HostState> hostState_ {ACTIVE};
|
|
std::unique_ptr<WorkerRunner> runner_ {};
|
|
|
|
napi_env hostEnv_ {nullptr};
|
|
napi_env workerEnv_ {nullptr};
|
|
|
|
napi_ref workerRef_ {nullptr};
|
|
napi_ref parentPort_ {nullptr};
|
|
|
|
std::map<std::string, std::list<WorkerListener*>> eventListeners_ {};
|
|
std::map<std::string, std::list<WorkerListener*>> parentPortEventListeners_ {};
|
|
|
|
std::recursive_mutex liveStatusLock_ {};
|
|
};
|
|
} // namespace CompilerRuntime::WorkerModule
|
|
#endif // JS_WORKER_MODULE_WORKER_WORKER_H_
|