• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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