• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "core/common/multi_thread_build_manager.h"
17 
18 #ifdef FFRT_SUPPORT
19 #include "ffrt_inner.h"
20 #endif
21 #include "base/log/log_wrapper.h"
22 #include "base/log/ace_trace.h"
23 #include "base/memory/referenced.h"
24 #include "base/utils/system_properties.h"
25 #include "core/common/container.h"
26 #include "core/pipeline_ng/pipeline_context.h"
27 
28 namespace OHOS::Ace {
29 namespace {
30 #ifdef FFRT_SUPPORT
31 constexpr uint32_t MAX_THREAD_NUM = 3;
32 constexpr uint32_t ASYNC_UITASK_QOS = 5;
33 std::unique_ptr<ffrt::queue> asyncUITaskQueue = nullptr;
34 #endif
35 }
36 thread_local bool MultiThreadBuildManager::isThreadSafeNodeScope_ = false;
37 thread_local bool MultiThreadBuildManager::isUIThread_ = false;
38 
GetInstance()39 MultiThreadBuildManager& MultiThreadBuildManager::GetInstance()
40 {
41     static MultiThreadBuildManager MultiThreadBuildManager;
42     return MultiThreadBuildManager;
43 }
44 
MultiThreadBuildManager()45 MultiThreadBuildManager::MultiThreadBuildManager()
46 {
47     InitAsyncUITaskQueue();
48 }
49 
InitOnUIThread()50 void MultiThreadBuildManager::InitOnUIThread()
51 {
52     isUIThread_ = true;
53 }
54 
InitAsyncUITaskQueue()55 void MultiThreadBuildManager::InitAsyncUITaskQueue()
56 {
57 #ifdef FFRT_SUPPORT
58     asyncUITaskQueue = std::make_unique<ffrt::queue>(ffrt::queue_concurrent,
59         "ArkUIAsyncUITask", ffrt::queue_attr().max_concurrency(MAX_THREAD_NUM));
60 #endif
61 }
62 
IsOnUIThread()63 bool MultiThreadBuildManager::IsOnUIThread()
64 {
65     return isUIThread_;
66 }
67 
CheckOnUIThread()68 bool MultiThreadBuildManager::CheckOnUIThread()
69 {
70     if (!IsOnUIThread()) {
71         TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "CheckOnUIThread failed");
72         return false;
73     }
74     return true;
75 }
76 
CheckNodeOnValidThread(NG::UINode * node)77 bool MultiThreadBuildManager::CheckNodeOnValidThread(NG::UINode* node)
78 {
79     if (!node) {
80         TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "CheckNodeOnValidThread failed. node is nullptr");
81         return false;
82     }
83     if (!node->IsFree() && !MultiThreadBuildManager::IsOnUIThread()) {
84         TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "CheckNodeOnValidThread failed. unfree node not run on main thread");
85         return false;
86     }
87     return true;
88 }
89 
SetIsThreadSafeNodeScope(bool isThreadSafeNodeScope)90 void MultiThreadBuildManager::SetIsThreadSafeNodeScope(bool isThreadSafeNodeScope)
91 {
92     isThreadSafeNodeScope_ = isThreadSafeNodeScope;
93 }
94 
IsThreadSafeNodeScope()95 bool MultiThreadBuildManager::IsThreadSafeNodeScope()
96 {
97     return isThreadSafeNodeScope_ || SystemProperties::GetDebugThreadSafeNodeEnabled();
98 }
99 
PostAsyncUITask(int32_t contextId,std::function<void ()> && asyncUITask,std::function<void ()> && onFinishTask)100 bool MultiThreadBuildManager::PostAsyncUITask(int32_t contextId, std::function<void()>&& asyncUITask,
101     std::function<void()>&& onFinishTask)
102 {
103     ContainerScope scope(contextId);
104     auto container = Container::Current();
105     CHECK_NULL_RETURN(container, false);
106     auto taskExecutor = container->GetTaskExecutor();
107     CHECK_NULL_RETURN(taskExecutor, false);
108 #ifdef FFRT_SUPPORT
109     if (!asyncUITaskQueue) {
110         return false;
111     }
112     auto result = asyncUITaskQueue->submit_h([contextId,
113         asyncUITask = std::move(asyncUITask), onFinishTask = std::move(onFinishTask)]() {
114         ContainerScope scope(contextId);
115         asyncUITask();
116         auto container = Container::Current();
117         CHECK_NULL_VOID(container);
118         auto taskExecutor = container->GetTaskExecutor();
119         CHECK_NULL_VOID(taskExecutor);
120         taskExecutor->PostTask([contextId, onFinishTask = std::move(onFinishTask)]() {
121             ContainerScope scope(contextId);
122             onFinishTask();
123             }, TaskExecutor::TaskType::UI, "ArkUIAsyncUIOnFinishTask", PriorityType::IMMEDIATE);
124     }, ffrt::task_attr().qos(ASYNC_UITASK_QOS));
125     return result != nullptr;
126 #else
127     return taskExecutor->PostTask([contextId,
128         asyncUITask = std::move(asyncUITask), onFinishTask = std::move(onFinishTask)]() {
129         ContainerScope scope(contextId);
130         asyncUITask();
131         auto container = Container::Current();
132         CHECK_NULL_VOID(container);
133         auto taskExecutor = container->GetTaskExecutor();
134         CHECK_NULL_VOID(taskExecutor);
135         taskExecutor->PostTask([contextId, onFinishTask = std::move(onFinishTask)]() {
136             ContainerScope scope(contextId);
137             onFinishTask();
138             }, TaskExecutor::TaskType::UI, "ArkUIAsyncUIOnFinishTask", PriorityType::IMMEDIATE);
139         }, TaskExecutor::TaskType::BACKGROUND, "ArkUIAsyncUITask");
140 #endif
141 }
142 
PostUITask(int32_t contextId,std::function<void ()> && uiTask)143 bool MultiThreadBuildManager::PostUITask(int32_t contextId, std::function<void()>&& uiTask)
144 {
145     ContainerScope scope(contextId);
146     auto container = Container::Current();
147     CHECK_NULL_RETURN(container, false);
148     auto taskExecutor = container->GetTaskExecutor();
149     CHECK_NULL_RETURN(taskExecutor, false);
150     return taskExecutor->PostTask([contextId, uiTask = std::move(uiTask)]() {
151         ContainerScope scope(contextId);
152         uiTask();
153         }, TaskExecutor::TaskType::UI, "ArkUISyncUITask", PriorityType::IMMEDIATE);
154 }
155 
PostUITaskAndWait(int32_t contextId,std::function<void ()> && uiTask)156 bool MultiThreadBuildManager::PostUITaskAndWait(int32_t contextId, std::function<void()>&& uiTask)
157 {
158     ContainerScope scope(contextId);
159     auto container = Container::Current();
160     CHECK_NULL_RETURN(container, false);
161     auto taskExecutor = container->GetTaskExecutor();
162     CHECK_NULL_RETURN(taskExecutor, false);
163     return taskExecutor->PostSyncTask([contextId, uiTask = std::move(uiTask)]() {
164         ContainerScope scope(contextId);
165         uiTask();
166         }, TaskExecutor::TaskType::UI, "ArkUISyncTaskAndWait", PriorityType::IMMEDIATE);
167 }
168 } // namespace OHOS::Ace