HILOG_INFO("worker:: Worker start constructor");
Worker* worker = nullptr;
if (limitSign) {
//RestrictedWorker的处理逻辑
......
} else {
//最大worker数
int maxWorkers = (version == WorkerVersion::NEW) ? MAX_THREAD_WORKERS : MAX_WORKERS;
#if defined(OHOS_PLATFORM)
maxWorkers = OHOS::system::GetIntParameter<int>("persist.commonlibrary.maxworkers", maxWorkers);
#endif
std::lock_guard<std::mutex> lock(g_workersMutex);
// 当前worker数达到最大限制worker数,抛出异常
if (static_cast<int>(g_workers.size()) >= maxWorkers) {
HILOG_ERROR("worker:: the number of workers exceeds the maximum");
ErrorHelper::ThrowError(env,
ErrorHelper::ERR_WORKER_INITIALIZATION, "the number of workers exceeds the maximum.");
return nullptr;
}
// 2. new worker instance
worker = new Worker(env, nullptr);
......
// worker实例加入list
g_workers.push_back(worker);
}
......
// 3. execute in thread
char* script = NapiHelper::GetString(env, args[0]);
if (script == nullptr) {
HILOG_ERROR("worker:: the file path is invaild, maybe path is null");
ErrorHelper::ThrowError(env,
ErrorHelper::ERR_WORKER_INVALID_FILEPATH, "the file path is invaild, maybe path is null.");
return nullptr;
}
napi_wrap(
env, thisVar, worker,
// js对象准备gc时,终止worker
[](napi_env env, void* data, void* hint) {
Worker* worker = reinterpret_cast<Worker*>(data);
{
std::lock_guard<std::recursive_mutex> lock(worker->liveStatusLock_);
if (worker->UpdateHostState(INACTIVE)) {
#if defined(ENABLE_WORKER_EVENTHANDLER)
if (!worker->isMainThreadWorker_) {
worker->CloseHostHandle();
}
#else
worker->CloseHostHandle();
#endif
worker->ReleaseHostThreadContent();
}
if (!worker->IsRunning()) {
HILOG_DEBUG("worker:: worker is not in running");
return;
}
worker->TerminateInner();
}
},
nullptr, &worker->workerRef_);
// worker线程启动执行
worker->StartExecuteInThread(env, script);
return thisVar;
}
```
启动worker线程
```
void Worker::StartExecuteInThread(napi_env env, const char* script)
{
HILOG_INFO("worker:: Start execute in the thread!");
// 1. init hostHandle in host loop
uv_loop_t* loop = NapiHelper::GetLibUV(env);
if (loop == nullptr) {
ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "engine loop is null");
CloseHelp:eletePointer(script, true);
return;
}
GetContainerScopeId(env);
//初始化uv句柄,宿主的loop handle
#if defined(ENABLE_WORKER_EVENTHANDLER)
if (!OHOS::AppExecFwk::EventRunner::IsAppMainThread()) {
isMainThreadWorker_ = false;
InitHostHandle(loop);
} else {
HILOG_DEBUG("worker:: eventrunner should be nullptr if the current thread is not the main thread");
}
#else
InitHostHandle(loop);
#endif
// 2. copy the script
//寻找worker线程文件
script_ = std::string(script);
// isBundle : FA mode and BundlePack.
bool isBundle = reinterpret_cast<NativeEngine*>(env)->GetIsBundle();
// if worker file is packed in har, need find moduleName in hostVM, and concat new recordName.
bool isHar = script_.find_first_of(PathHelper::NAME_SPACE_TAG) == 0;
if ((isHar && script_.find(PathHelper:REFIX_BUNDLE) == std::string::npos) ||
(!isBundle && script_.find_first_of(PathHelper:OINT_TAG) == 0)) {
PathHelper::ConcatFileNameForWorker(env, script_, fileName_, isRelativePath_);
HILOG_DEBUG("worker:: Concated worker recordName: %{public}s, fileName: %{public}s",
script_.c_str(), fileName_.c_str());
}
// check the path is vaild.
bool isNormalizedOhmUrlPack = reinterpret_cast<NativeEngine*>(env)->GetIsNormalizedOhmUrlPack();
if (!isNormalizedOhmUrlPack && !isBundle) {
if (!PathHelper::CheckWorkerPath(env, script_, isHar, isRelativePath_)) {
HILOG_ERROR("worker:: the file path is invaild, can't find the file : %{public}s.", script);
CloseHelp:eletePointer(script, true);
ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_INVALID_FILEPATH,
"the file path is invaild, can't find the file.");
return;
}
}
// 3. create WorkerRunner to Execute
if (!runner_) {
// 创建WorkerRunner线程,线程启动后回调ExecuteThread
runner_ = std::make_unique<WorkerRunner>(WorkerStartCallback(ExecuteInThread, this));
}
if (runner_) {
//Worker线程启动
runner_->Execute(); // start a new thread
} else {
HILOG_ERROR("runner_ is nullptr");
}
CloseHelp:eletePointer(script, true);
}
```
Worker线程创建后执行Executethread
```
void Worker::ExecuteInThread(const void* data)
{
HITRACE_HELPER_START_TRACE(__PRETTY_FUNCTION__);
HILOG_INFO("worker:: Execute in the thread!");
auto worker = reinterpret_cast<Worker*>(const_cast<void*>(data));
// 1. create a runtime, nativeengine
napi_env workerEnv = nullptr;
{
std::lock_guard<std::recursive_mutex> lock(worker->liveStatusLock_);
if (worker->HostIsStop()) {
HILOG_ERROR("worker:: host thread is stop");
CloseHelp:eletePointer(worker, false);
return;
}
napi_env env = worker->GetHostEnv();
//创建runtime,为worker创建ArkNativeEngine
napi_create_runtime(env, &workerEnv);
if (workerEnv == nullptr) {
HILOG_ERROR("worker:: Worker create runtime error");
ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "Worker create runtime error");
return;
}
// mark worker env is workerThread
reinterpret_cast<NativeEngine*>(workerEnv)->MarkWorkerThread();
// for load balance in taskpool
reinterpret_cast<NativeEngine*>(env)->IncreaseSubEnvCounter();
worker->SetWorkerEnv(workerEnv);
}
//根据workerEnv得到worker线程的loop
uv_loop_t* loop = worker->GetWorkerLoop();
if (loop == nullptr) {
HILOG_ERROR("worker:: Worker loop is nullptr");
return;
}
// 2. add some preparation for the worker
//执行worker初始化操作
if (worker->repareForWorkerInstance()) {
worker->workerOnMessageSignal_ = new uv_async_t;
// worker loop,初始化workerOnMessageSignal_ handle,handle回调执行WorkerOnMessage
uv_async_init(loop, worker->workerOnMessageSignal_, reinterpret_cast<uv_async_cb>(Worker::WorkerOnMessage));
worker->workerOnMessageSignal_->data = worker;
#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
uv_async_init(loop, &worker->debuggerOnPostTaskSignal_, reinterpret_cast<uv_async_cb>(
Worker::HandleDebuggerTask));
#endif
//worker状态置为RUNNING
worker->UpdateWorkerState(RUNNING);
// in order to invoke worker send before subThread start
uv_async_send(worker->workerOnMessageSignal_);
HITRACE_HELPER_FINISH_TRACE;
//运行事件循环
// 3. start worker loop
worker->Loop();
} else {
HILOG_ERROR("worker:: worker PrepareForWorkerInstance fail");
worker->UpdateWorkerState(TERMINATED);
HITRACE_HELPER_FINISH_TRACE;
}
// worker初始化失败或worker的loop结束,释放worker线程资源:删除监听、端口,清空worker消息队列
worker->ReleaseWorkerThreadContent();
std::lock_guard<std::recursive_mutex> lock(worker->liveStatusLock_);
//如果宿主stop,直接释放worker;否则向宿主消息队列添加nullptr,宿主接收信号后关闭回调
if (worker->HostIsStop()) {
HILOG_INFO("worker:: host is stopped");
CloseHelp:eletePointer(worker, false);
} else {
worker->ublishWorkerOverSignal();
}
}
```
napi_value Worker::Terminate(napi_env env, napi_callback_info cbinfo)
{
HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__);
napi_value thisVar = nullptr;
napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr);
Worker* worker = nullptr;
napi_unwrap(env, thisVar, reinterpret_cast<void**>(&worker));
if (worker == nullptr) {
HILOG_ERROR("worker:: worker is nullptr when Terminate, maybe worker is terminated");
WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "worker is nullptr when Terminate");
return nullptr;
}
if (worker->IsTerminated() || worker->IsTerminating()) {
HILOG_DEBUG("worker:: worker is not in running when Terminate");
return nullptr;
}
worker->TerminateInner();
return NapiHelper::GetUndefinedValue(env);
}
void Worker::TerminateInner()
{
if (IsTerminated() || IsTerminating()) {
HILOG_INFO("worker:: worker is not in running when TerminateInner");
return;
}
//worker状态置为TERMINATEING
// 1. Update State
UpdateWorkerState(TERMINATEING);
//发送nullptr信号,worker线程接收到后执行TerminateWorker
// 2. send null signal
PostMessageInner(nullptr);
}