1 /* 2 * Copyright (c) 2022 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 JS_CONCURRENT_MODULE_WORKER_WORKER_H 17 #define JS_CONCURRENT_MODULE_WORKER_WORKER_H 18 19 #include <condition_variable> 20 #include <list> 21 #include <map> 22 #include <mutex> 23 24 #include "helper/napi_helper.h" 25 #include "helper/object_helper.h" 26 #include "message_queue.h" 27 #include "napi/native_api.h" 28 #include "napi/native_node_api.h" 29 #include "native_engine/native_engine.h" 30 #include "native_engine/worker_manager.h" 31 #include "worker_runner.h" 32 #if defined(ENABLE_WORKER_EVENTHANDLER) 33 #include "event_handler.h" 34 #endif 35 36 namespace Commonlibrary::Concurrent::WorkerModule { 37 using namespace Commonlibrary::Concurrent::Common::Helper; 38 39 enum class WorkerPriority { INVALID = -1, HIGH = 0, MEDIUM, LOW, IDLE, DEADLINE, VIP, MAX }; 40 41 class Worker { 42 public: 43 enum RunnerState { STARTING, RUNNING, TERMINATEING, TERMINATED }; 44 enum HostState { ACTIVE, INACTIVE }; 45 enum ListenerMode { ONCE, PERMANENT }; 46 enum ScriptMode { CLASSIC, MODULE }; 47 48 using DebuggerPostTask = std::function<void()>; 49 50 struct WorkerListener { WorkerListenerWorkerListener51 WorkerListener(napi_env env, napi_ref callback, ListenerMode mode) 52 : env_(env), callback_(callback), mode_(mode) 53 {} 54 ~WorkerListenerWorkerListener55 ~WorkerListener() 56 { 57 NapiHelper::DeleteReference(env_, callback_); 58 callback_ = nullptr; 59 } 60 NextIsAvailableWorkerListener61 bool NextIsAvailable() const 62 { 63 return mode_ != ONCE; 64 } 65 SetModeWorkerListener66 void SetMode(ListenerMode mode) 67 { 68 mode_ = mode; 69 } 70 71 bool operator==(const WorkerListener& listener) const; 72 73 napi_env env_ {NULL}; 74 napi_ref callback_ {NULL}; 75 ListenerMode mode_ {PERMANENT}; 76 }; 77 78 struct FindWorkerListener { FindWorkerListenerFindWorkerListener79 FindWorkerListener(napi_env env, napi_ref ref) : env_(env), ref_(ref) {} 80 operatorFindWorkerListener81 bool operator()(const WorkerListener* listener) const 82 { 83 napi_value compareObj = NapiHelper::GetReferenceValue(env_, listener->callback_); 84 napi_value obj = NapiHelper::GetReferenceValue(env_, ref_); 85 // the env of listener and cmp listener must be same env because of Synchronization method 86 return NapiHelper::StrictEqual(env_, compareObj, obj); 87 } 88 89 napi_env env_ {nullptr}; 90 napi_ref ref_ {nullptr}; 91 }; 92 93 struct WorkerParams { 94 std::string name_ {}; 95 ScriptMode type_ {CLASSIC}; 96 WorkerPriority workerPriority_ { WorkerPriority::INVALID }; 97 }; 98 99 struct WorkerWrapper { WorkerWrapperWorkerWrapper100 explicit WorkerWrapper(Worker* worker) : workerPtr_(worker) {} 101 GetWorkerWorkerWrapper102 Worker* GetWorker() const 103 { 104 return workerPtr_; 105 } 106 107 Worker* workerPtr_ {nullptr}; 108 }; 109 110 /** 111 * Creates a worker instance. 112 * 113 * @param env NAPI environment parameters. 114 * @param thisVar URL of the script to be executed by the worker. 115 */ 116 Worker(napi_env env, napi_ref thisVar); 117 118 /** 119 * The destructor of the Worker. 120 */ 121 ~Worker(); 122 123 /** 124 * The host thread receives the information. 125 * 126 * @param req The value of the object passed in by the js layer. 127 */ 128 static void HostOnMessage(const uv_async_t* req); 129 130 /** 131 * The host thread receives the information. 132 * 133 * @param req The value of the object passed in by the js layer. 134 */ 135 static void HostOnError(const uv_async_t* req); 136 137 /** 138 * The host thread receives the worker exception. 139 * 140 * @param req The value of the object passed in by the js layer. 141 */ 142 static void HostOnAllErrors(const uv_async_t* req); 143 144 /** 145 * The worker thread receives the information. 146 * 147 * @param req The value of the object passed in by the js layer. 148 */ 149 static void WorkerOnMessage(const uv_async_t* req); 150 151 /** 152 * ExecuteIn in thread. 153 * 154 * @param data The worker pointer. 155 */ 156 static void ExecuteInThread(const void* data); 157 158 /** 159 * Post a message. 160 * 161 * @param env NAPI environment parameters. 162 * @param thisVar The callback information of the js layer. 163 */ 164 static napi_value PostMessage(napi_env env, napi_callback_info cbinfo); 165 166 /** 167 * Post a message, if has sendable objects in it pass sendable objects' reference. 168 * 169 * @param env NAPI environment parameters. 170 * @param thisVar The callback information of the js layer. 171 */ 172 static napi_value PostMessageWithSharedSendable(napi_env env, napi_callback_info cbinfo); 173 174 /** 175 * postMessage implementation 176 * 177 * @param env NAPI environment parameters. 178 * @param thisVar The callback information of the js layer. 179 */ 180 static napi_value CommonPostMessage(napi_env env, napi_callback_info cbinfo, bool cloneSendable); 181 182 /** 183 * Add event listeners to host. 184 * 185 * @param env NAPI environment parameters. 186 * @param cbinfo The callback information of the js layer. 187 */ 188 static napi_value PostMessageToHost(napi_env env, napi_callback_info cbinfo); 189 190 /** 191 * Post a message, if has sendable objects in it pass sendable objects' reference. 192 * 193 * @param env NAPI environment parameters. 194 * @param thisVar The callback information of the js layer. 195 */ 196 static napi_value PostMessageWithSharedSendableToHost(napi_env env, napi_callback_info cbinfo); 197 198 /** 199 * postMessage implementation 200 * 201 * @param env NAPI environment parameters. 202 * @param thisVar The callback information of the js layer. 203 */ 204 static napi_value CommonPostMessageToHost(napi_env env, napi_callback_info cbinfo, bool cloneSendable); 205 206 /** 207 * Terminates the worker thread to stop the worker from receiving messages. 208 * 209 * @param env NAPI environment parameters. 210 * @param cbinfo The callback information of the js layer. 211 */ 212 static napi_value Terminate(napi_env env, napi_callback_info cbinfo); 213 214 /** 215 * Close the worker. 216 * 217 * @param env NAPI environment parameters. 218 * @param cbinfo The callback information of the js layer. 219 */ 220 static napi_value CloseWorker(napi_env env, napi_callback_info cbinfo); 221 222 /** 223 * Adds an event listener to the worker. 224 * 225 * @param env NAPI environment parameters. 226 * @param cbinfo The callback information of the js layer. 227 */ 228 static napi_value On(napi_env env, napi_callback_info cbinfo); 229 230 /** 231 * Adds an event listener to the worker and removes the event listener automatically after it is invoked once. 232 * 233 * @param env NAPI environment parameters. 234 * @param cbinfo The callback information of the js layer. 235 */ 236 static napi_value Once(napi_env env, napi_callback_info cbinfo); 237 238 /** 239 * Removes an event listener to the worker. 240 * 241 * @param env NAPI environment parameters. 242 * @param cbinfo The callback information of the js layer. 243 */ 244 static napi_value Off(napi_env env, napi_callback_info cbinfo); 245 246 /** 247 * Add event listeners. 248 * 249 * @param env NAPI environment parameters. 250 * @param cbinfo The callback information of the js layer. 251 */ 252 static napi_value AddEventListener(napi_env env, napi_callback_info cbinfo); 253 254 /** 255 * Dispatch the event. 256 * 257 * @param env NAPI environment parameters. 258 * @param cbinfo The callback information of the js layer. 259 */ 260 static napi_value DispatchEvent(napi_env env, napi_callback_info cbinfo); 261 262 /** 263 * Remove the event listener. 264 * 265 * @param env NAPI environment parameters. 266 * @param cbinfo The callback information of the js layer. 267 */ 268 static napi_value RemoveEventListener(napi_env env, napi_callback_info cbinfo); 269 270 /** 271 * Remove all listener. 272 * 273 * @param env NAPI environment parameters. 274 * @param cbinfo The callback information of the js layer. 275 */ 276 static napi_value RemoveAllListener(napi_env env, napi_callback_info cbinfo); 277 278 /** 279 * Add the listener. 280 * 281 * @param env NAPI environment parameters. 282 * @param cbinfo The callback information of the js layer. 283 */ 284 static napi_value AddListener(napi_env env, napi_callback_info cbinfo, ListenerMode mode); 285 286 /** 287 * Remove the listener. 288 * 289 * @param env NAPI environment parameters. 290 * @param cbinfo The callback information of the js layer. 291 */ 292 static napi_value RemoveListener(napi_env env, napi_callback_info cbinfo); 293 294 /** 295 * The constructor of worker. 296 * 297 * @param env NAPI environment parameters. 298 * @param cbinfo The callback information of the js layer. 299 */ 300 static napi_value LimitedWorkerConstructor(napi_env env, napi_callback_info cbinfo); 301 static napi_value ThreadWorkerConstructor(napi_env env, napi_callback_info cbinfo); 302 static napi_value WorkerConstructor(napi_env env, napi_callback_info cbinfo); 303 static napi_value Constructor(napi_env env, napi_callback_info cbinfo, bool limitSign = false, 304 WorkerVersion version = WorkerVersion::NONE); 305 306 /** 307 * Initialize the worker and port. 308 * 309 * @param env NAPI environment parameters. 310 * @param cbinfo The callback information of the js layer. 311 */ 312 static napi_value InitWorker(napi_env env, napi_value exports); 313 static void InitPriorityObject(napi_env env, napi_value exports); 314 static napi_value InitPort(napi_env env, napi_value exports); 315 316 /** 317 * Cancel the task. 318 * 319 * @param env NAPI environment parameters. 320 * @param cbinfo The callback information of the js layer. 321 */ 322 static napi_value CancelTask(napi_env env, napi_callback_info cbinfo); 323 324 /** 325 * The parent port cancels the task. 326 * 327 * @param env NAPI environment parameters. 328 * @param cbinfo The callback information of the js layer. 329 */ 330 static napi_value ParentPortCancelTask(napi_env env, napi_callback_info cbinfo); 331 332 /** 333 * The parent port adds an event listener. 334 * 335 * @param env NAPI environment parameters. 336 * @param cbinfo The callback information of the js layer. 337 */ 338 static napi_value ParentPortAddEventListener(napi_env env, napi_callback_info cbinfo); 339 340 /** 341 * The parent port removes all event listener. 342 * 343 * @param env NAPI environment parameters. 344 * @param cbinfo The callback information of the js layer. 345 */ 346 static napi_value ParentPortRemoveAllListener(napi_env env, napi_callback_info cbinfo); 347 348 /** 349 * The parent port dispatch the event listener. 350 * 351 * @param env NAPI environment parameters. 352 * @param cbinfo The callback information of the js layer. 353 */ 354 static napi_value ParentPortDispatchEvent(napi_env env, napi_callback_info cbinfo); 355 356 /** 357 * The parent port removes the event listener. 358 * 359 * @param env NAPI environment parameters. 360 * @param cbinfo The callback information of the js layer. 361 */ 362 static napi_value ParentPortRemoveEventListener(napi_env env, napi_callback_info cbinfo); 363 364 /** 365 * Register a globalCallObject on host side. 366 * 367 * @param env NAPI environment parameters. 368 * @param cbinfo The callback information of the js layer. 369 */ 370 static napi_value RegisterGlobalCallObject(napi_env env, napi_callback_info cbinfo); 371 372 /** 373 * Unregister the specific globalCallObject on host side. 374 * 375 * @param env NAPI environment parameters. 376 * @param cbinfo The callback information of the js layer. 377 */ 378 static napi_value UnregisterGlobalCallObject(napi_env env, napi_callback_info cbinfo); 379 380 /** 381 * Post a global synchronized call request to an object registered on host side. 382 * 383 * @param env NAPI environment parameters. 384 * @param cbinfo The callback information of the js layer. 385 */ 386 static napi_value GlobalCall(napi_env env, napi_callback_info cbinfo); 387 388 static void HostOnGlobalCall(const uv_async_t* req); 389 390 static bool CanCreateWorker(napi_env env, WorkerVersion target); 391 392 static WorkerParams* CheckWorkerArgs(napi_env env, napi_value argsValue, 393 WorkerVersion version = WorkerVersion::NONE); 394 395 static napi_value ParseTransferListArg(napi_env env, napi_value secondArg, bool& isValid, 396 const std::string& errMsg); 397 398 static WorkerPriority GetPriorityArg(napi_env env, napi_value argsValue); 399 400 static void WorkerThrowError(napi_env env, int32_t errCode, const char* errMessage = nullptr); 401 402 static void WorkerDestructor(napi_env env, void* data, void* hint); 403 static void WorkerHostEnvCleanCallback(void* data); 404 static void LimitedWorkerHostEnvCleanCallback(void* data); 405 406 #if defined(ENABLE_WORKER_EVENTHANDLER) 407 static std::shared_ptr<OHOS::AppExecFwk::EventHandler> GetMainThreadHandler(); 408 #endif 409 410 void StartExecuteInThread(napi_env env, const char* script); 411 412 bool UpdateWorkerState(RunnerState state); 413 bool UpdateHostState(HostState state); 414 IsNotTerminate()415 bool IsNotTerminate() const 416 { 417 return runnerState_.load(std::memory_order_acquire) <= RUNNING; 418 } 419 IsRunning()420 bool IsRunning() const 421 { 422 return runnerState_.load(std::memory_order_acquire) == RUNNING; 423 } 424 IsTerminated()425 bool IsTerminated() const 426 { 427 return runnerState_.load(std::memory_order_acquire) >= TERMINATED; 428 } 429 IsTerminating()430 bool IsTerminating() const 431 { 432 return runnerState_.load(std::memory_order_acquire) == TERMINATEING; 433 } 434 SetScriptMode(ScriptMode mode)435 void SetScriptMode(ScriptMode mode) 436 { 437 scriptMode_ = mode; 438 } 439 440 void AddListenerInner(napi_env env, const char* type, const WorkerListener* listener); 441 void RemoveListenerInner(napi_env env, const char* type, napi_ref callback); 442 void RemoveAllListenerInner(); 443 void EraseWorker(); GetWorkerLoop()444 uv_loop_t* GetWorkerLoop() const 445 { 446 if (workerEnv_ != nullptr) { 447 return NapiHelper::GetLibUV(workerEnv_); 448 } 449 return nullptr; 450 } 451 SetWorkerEnv(napi_env workerEnv)452 void SetWorkerEnv(napi_env workerEnv) 453 { 454 workerEnv_ = workerEnv; 455 std::unique_lock<std::mutex> lock(workerEnvCallbackQueueMutex_); 456 for (; !workerEnvCallbackQueue_.empty(); workerEnvCallbackQueue_.pop()) { 457 workerEnvCallbackQueue_.front()(workerEnv_); 458 } 459 } 460 GetScript()461 std::string GetScript() const 462 { 463 return script_; 464 } 465 GetName()466 std::string GetName() const 467 { 468 return name_; 469 } 470 ClearWorkerTasks()471 bool ClearWorkerTasks() 472 { 473 if (hostEnv_ != nullptr) { 474 workerMessageQueue_.Clear(hostEnv_); 475 return true; 476 } 477 return false; 478 } 479 HostIsStop()480 bool HostIsStop() const 481 { 482 return hostState_.load(std::memory_order_acquire) == INACTIVE; 483 } 484 IsSameWorkerEnv(napi_env env)485 bool IsSameWorkerEnv(napi_env env) const 486 { 487 return workerEnv_ == env; 488 } 489 Loop()490 void Loop() const 491 { 492 uv_loop_t* loop = GetWorkerLoop(); 493 if (loop != nullptr) { 494 uv_run(loop, UV_RUN_DEFAULT); 495 } else { 496 return; 497 } 498 } 499 RegisterCallbackForWorkerEnv(std::function<void (napi_env)> callback)500 void RegisterCallbackForWorkerEnv(std::function<void (napi_env)> callback) 501 { 502 std::unique_lock<std::mutex> lock(workerEnvCallbackQueueMutex_); 503 workerEnvCallbackQueue_.push(callback); 504 if (workerEnv_ != nullptr) { 505 for (; !workerEnvCallbackQueue_.empty(); workerEnvCallbackQueue_.pop()) { 506 workerEnvCallbackQueue_.front()(workerEnv_); 507 } 508 } 509 } 510 GetWorkerEnv()511 napi_env GetWorkerEnv() const 512 { 513 return workerEnv_; 514 } 515 GetHostEnv()516 napi_env GetHostEnv() const 517 { 518 return hostEnv_; 519 } 520 SetQOSLevelUpdatedCallback(std::function<void ()> callback)521 void SetQOSLevelUpdatedCallback(std::function<void()> callback) 522 { 523 qosUpdatedCallback_ = callback; 524 } 525 526 napi_env CreateWorkerEnv(); 527 528 private: 529 void WorkerOnMessageInner(); 530 void HostOnMessageInner(); 531 void HostOnErrorInner(); 532 void HostOnAllErrorsInner(); 533 void HostOnMessageErrorInner(); 534 void HostOnGlobalCallInner(); 535 void WorkerOnMessageErrorInner(); 536 void WorkerOnErrorInner(napi_value error); 537 538 void HandleHostException() const; 539 void HandleException(); 540 void HandleWorkerUncaughtException(napi_env env, napi_value exception); 541 void HandleUncaughtException(napi_value exception); 542 bool CallWorkerFunction(size_t argc, const napi_value* argv, const char* methodName, bool tryCatch); 543 void CallHostFunction(size_t argc, const napi_value* argv, const char* methodName) const; 544 545 bool HandleEventListeners(napi_env env, napi_value recv, size_t argc, const napi_value* argv, const char* type); 546 void ParentPortHandleEventListeners(napi_env env, napi_value recv, size_t argc, 547 const napi_value* argv, const char* type, bool tryCatch); 548 void TerminateInner(); 549 550 void PostMessageInner(MessageDataType data); 551 void PostMessageToHostInner(MessageDataType data); 552 553 void TerminateWorker(); 554 555 void CloseInner(); 556 557 void PublishWorkerOverSignal(); 558 void CloseWorkerCallback(); 559 void CloseHostCallback(); 560 561 void PostWorkerOverTask(); 562 void PostWorkerErrorTask(); 563 void PostWorkerExceptionTask(); 564 void PostWorkerMessageTask(); 565 void PostWorkerGlobalCallTask(); 566 static bool IsValidWorker(Worker* worker); 567 static bool IsValidLimitedWorker(Worker* limitedWorker); 568 static void HostEnvCleanCallbackInner(Worker* worker); 569 570 void InitHostHandle(uv_loop_t* loop); 571 void CloseHostHandle(); 572 573 void ReleaseWorkerThreadContent(); 574 void ReleaseHostThreadContent(); 575 bool PrepareForWorkerInstance(); 576 void ApplyNameSetting(); 577 void ParentPortAddListenerInner(napi_env env, const char* type, const WorkerListener* listener); 578 void ParentPortRemoveAllListenerInner(); 579 void ParentPortRemoveListenerInner(napi_env env, const char* type, napi_ref callback); 580 void GetContainerScopeId(napi_env env); 581 582 void AddGlobalCallObject(const std::string &instanceName, napi_ref obj); 583 bool RemoveGlobalCallObject(const std::string &instanceName); 584 void ClearGlobalCallObject(); 585 void AddGlobalCallError(int32_t errCode, napi_value errData = nullptr); 586 void HandleGlobalCallError(napi_env env); 587 void ClearGlobalCallError(napi_env env); 588 void InitGlobalCallStatus(napi_env env); 589 void IncreaseGlobalCallId(); 590 591 void ClearHostMessage(napi_env env); 592 593 bool IsPublishWorkerOverSignal(); 594 595 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) 596 static void HandleDebuggerTask(const uv_async_t* req); 597 void DebuggerOnPostTask(std::function<void()>&& task); 598 #endif 599 600 #ifdef ENABLE_QOS 601 void SetQOSLevel(); 602 #endif 603 std::string script_ {}; 604 std::string fileName_ {}; 605 std::string name_ {}; 606 ScriptMode scriptMode_ {CLASSIC}; 607 WorkerType workerType_ {WorkerType::THREAD_WORKER}; 608 bool isLimitedWorker_ {false}; 609 bool isRelativePath_ {false}; 610 int32_t scopeId_ {-1}; 611 612 MessageQueue workerMessageQueue_ {}; 613 MessageQueue hostMessageQueue_ {}; 614 std::mutex globalCallMutex_; 615 MarkedMessageQueue hostGlobalCallQueue_ {}; 616 MessageQueue workerGlobalCallQueue_ {}; 617 MessageQueue errorQueue_ {}; 618 MessageQueue exceptionQueue_ {}; 619 std::atomic<bool> workerOnMessageInitState_ {false}; 620 std::atomic<bool> workerOnTerminateInitState_ {false}; 621 622 uv_async_t* workerOnMessageSignal_ = nullptr; 623 uv_async_t* workerOnTerminateSignal_ = nullptr; 624 uv_async_t* hostOnMessageSignal_ = nullptr; 625 uv_async_t* hostOnErrorSignal_ = nullptr; 626 uv_async_t* hostOnAllErrorsSignal_ = nullptr; 627 uv_async_t* hostOnGlobalCallSignal_ = nullptr; 628 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) 629 uv_async_t* debuggerOnPostTaskSignal_ = nullptr; 630 std::mutex debuggerMutex_; 631 std::queue<DebuggerPostTask> debuggerQueue_ {}; 632 #endif 633 634 std::atomic<RunnerState> runnerState_ {STARTING}; 635 std::atomic<HostState> hostState_ {ACTIVE}; 636 std::unique_ptr<WorkerRunner> runner_ {}; 637 638 std::atomic<bool> isErrorExit_ = false; 639 640 napi_env hostEnv_ {nullptr}; 641 napi_env workerEnv_ {nullptr}; 642 643 napi_ref workerRef_ {nullptr}; 644 napi_ref workerPort_ {nullptr}; 645 646 std::map<std::string, std::list<WorkerListener*>> eventListeners_ {}; 647 std::map<std::string, std::list<WorkerListener*>> parentPortEventListeners_ {}; 648 std::unordered_map<std::string, napi_ref> globalCallObjects_ {}; 649 std::queue<std::pair<int32_t, napi_value>> globalCallErrors_ {}; 650 std::atomic<uint32_t> globalCallId_ = 1; // 0: reserved for error check 651 652 std::recursive_mutex liveStatusLock_ {}; 653 std::mutex workerOnmessageMutex_ {}; 654 655 std::condition_variable cv_; 656 std::atomic<bool> globalCallSuccess_ = true; 657 std::mutex workerEnvCallbackQueueMutex_; 658 std::queue<std::function<void(napi_env)> > workerEnvCallbackQueue_; 659 660 bool isMainThreadWorker_ = true; 661 bool isNewVersion_ = true; 662 std::atomic<bool> isTerminated_ = false; 663 std::atomic<bool> isHostEnvExited_ = false; 664 665 std::shared_ptr<WorkerWrapper> workerWrapper_ = nullptr; 666 WorkerPriority workerPriority_ = WorkerPriority::INVALID; 667 std::function<void()> qosUpdatedCallback_; 668 669 friend class WorkersTest; 670 }; 671 672 class ContainerScope { 673 public: ContainerScope(NativeEngine * engine,uint32_t scopeId)674 ContainerScope(NativeEngine* engine, uint32_t scopeId) 675 : engine_(engine), scopeId_(scopeId), initialized_(false) 676 { 677 if (engine_ != nullptr) { 678 initialized_ = engine_->InitContainerScopeFunc(scopeId_); 679 } 680 } 681 ~ContainerScope()682 ~ContainerScope() 683 { 684 if (engine_ != nullptr && initialized_) { 685 engine_->FinishContainerScopeFunc(scopeId_); 686 } 687 } 688 IsInitialized()689 bool IsInitialized() const 690 { 691 return initialized_; 692 } 693 694 private: 695 NativeEngine* engine_ {nullptr}; 696 int32_t scopeId_ {-1}; 697 bool initialized_ {false}; 698 }; 699 } // namespace Commonlibrary::Concurrent::WorkerModule 700 #endif // JS_CONCURRENT_MODULE_WORKER_WORKER_H 701