1 /* 2 * Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_THREAD_TASK_EXECUTOR_H 17 #define FOUNDATION_ACE_FRAMEWORKS_BASE_THREAD_TASK_EXECUTOR_H 18 19 #include <cstdint> 20 #include <functional> 21 22 #include "base/memory/ace_type.h" 23 #include "base/thread/cancelable_callback.h" 24 #include "base/utils/noncopyable.h" 25 26 namespace OHOS::Ace { 27 28 class TaskExecutor : public AceType { 29 DECLARE_ACE_TYPE(TaskExecutor, AceType); 30 ACE_DISALLOW_COPY_AND_MOVE(TaskExecutor); 31 32 public: 33 using Task = std::function<void()>; 34 using CancelableTask = CancelableCallback<void()>; 35 36 static constexpr int32_t TASK_TYPE_SIZE = 7; 37 enum class TaskType : uint32_t { 38 PLATFORM = 0, 39 UI, 40 IO, 41 GPU, 42 JS, 43 BACKGROUND, 44 UNKNOWN, 45 }; 46 47 ~TaskExecutor() override = default; 48 49 /** 50 * Post a task to the specified thread. 51 * 52 * @param task Task which need execution. 53 * @param type FrontendType of task, used to specify the thread. 54 * @return Returns 'true' whether task has been post successfully. 55 */ PostTask(Task && task,TaskType type)56 bool PostTask(Task&& task, TaskType type) const 57 { 58 return PostDelayedTask(std::move(task), type, 0); 59 } 60 61 /** 62 * Post a task to the specified thread. 63 * 64 * @param task Task which need execution. 65 * @param type FrontendType of task, used to specify the thread. 66 * @return Returns 'true' if task has been posted successfully. 67 */ PostTask(const Task & task,TaskType type)68 bool PostTask(const Task& task, TaskType type) const 69 { 70 return PostDelayedTask(task, type, 0); 71 } 72 73 /** 74 * Post a task to the specified thread with a trace id. 75 * 76 * @param task Task which need execution. 77 * @param type FrontendType of task, used to specify the thread. 78 * @param id The id to trace the task. 79 * @return Returns 'true' whether task has been post successfully. 80 */ PostTaskWithTraceId(Task && task,TaskType type,int32_t id)81 bool PostTaskWithTraceId(Task&& task, TaskType type, int32_t id) const 82 { 83 Task wrappedTask = WrapTaskWithTraceId(std::move(task), id); 84 return PostDelayedTask(std::move(wrappedTask), type, 0); 85 } 86 87 /** 88 * Post a task to the specified thread. 89 * 90 * @param task Task which need execution. 91 * @param type FrontendType of task, used to specify the thread. 92 * @param id The id to trace the task. 93 * @return Returns 'true' if task has been posted successfully. 94 */ PostTaskWithTraceId(const Task & task,TaskType type,int32_t id)95 bool PostTaskWithTraceId(const Task& task, TaskType type, int32_t id) const 96 { 97 Task wrappedTask = WrapTaskWithTraceId(Task(task), id); 98 return PostDelayedTask(std::move(wrappedTask), type, 0); 99 } 100 101 /** 102 * Post a delayed task to the specified thread. 103 * Never allow to post a background delayed task. 104 * 105 * @param task Task which need execution. 106 * @param type FrontendType of task, used to specify the thread. 107 * @param delayTime Wait a period of time in milliseconds before execution. 108 * @return Returns 'true' if task has been posted successfully. 109 */ PostDelayedTask(Task && task,TaskType type,uint32_t delayTime)110 bool PostDelayedTask(Task&& task, TaskType type, uint32_t delayTime) const 111 { 112 if (delayTime > 0 && type == TaskType::BACKGROUND) { 113 return false; 114 } 115 return OnPostTask(std::move(task), type, delayTime); 116 } 117 118 /** 119 * Post a delayed task to the specified thread. 120 * Never allow to post a background delayed task. 121 * 122 * @param task Task which need execution. 123 * @param type FrontendType of task, used to specify the thread. 124 * @param delayTime Wait a period of time in milliseconds before execution. 125 * @return Returns 'true' if task has been posted successfully. 126 */ PostDelayedTask(const Task & task,TaskType type,uint32_t delayTime)127 bool PostDelayedTask(const Task& task, TaskType type, uint32_t delayTime) const 128 { 129 return PostDelayedTask(Task(task), type, delayTime); 130 } 131 132 /** 133 * Post a task to the specified thread and wait until finished executing. 134 * Never allow to post a background synchronous task. 135 * 136 * @param task Task which need execution. 137 * @param type FrontendType of task, used to specify the thread. 138 * @return Returns 'true' whether task has been executed. 139 */ PostSyncTask(Task && task,TaskType type)140 bool PostSyncTask(Task&& task, TaskType type) const 141 { 142 if (!task || type == TaskType::BACKGROUND) { 143 return false; 144 } else if (WillRunOnCurrentThread(type)) { 145 task(); 146 return true; 147 } 148 return PostTaskAndWait(CancelableTask(std::move(task)), type); 149 } 150 151 /** 152 * Post a task to the specified thread and wait until finished executing. 153 * Never allow to post a background synchronous task. 154 * 155 * @param task Task which need execution. 156 * @param type FrontendType of task, used to specify the thread. 157 * @param timeoutMs Timeout in milliseconds before task execution. 158 * @return Returns 'true' whether task has been executed. 159 */ PostSyncTaskTimeout(const Task & task,TaskType type,uint32_t timeoutMs)160 bool PostSyncTaskTimeout(const Task& task, TaskType type, uint32_t timeoutMs) const 161 { 162 if (!task || type == TaskType::BACKGROUND) { 163 return false; 164 } else if (WillRunOnCurrentThread(type)) { 165 task(); 166 return true; 167 } 168 return PostTaskAndWait(CancelableTask(std::move(task)), type, std::chrono::milliseconds(timeoutMs)); 169 } 170 171 /** 172 * Post a task to the specified thread and wait until finished executing. 173 * Never allow to post a background synchronous task. 174 * 175 * @param task Task which need execution. 176 * @param type FrontendType of task, used to specify the thread. 177 * @return Returns 'true' whether task has been executed. 178 */ PostSyncTask(const Task & task,TaskType type)179 bool PostSyncTask(const Task& task, TaskType type) const 180 { 181 return PostSyncTask(Task(task), type); 182 } 183 184 /** 185 * Post a cancelable task to the specified thread and wait until finished executing. 186 * Never allow to post a background synchronous task. 187 * 188 * @param task Task which need execution. 189 * @param type FrontendType of task, used to specify the thread. 190 * @return Returns 'true' whether task has been executed. 191 */ PostSyncTask(CancelableTask && task,TaskType type)192 bool PostSyncTask(CancelableTask&& task, TaskType type) const 193 { 194 if (!task || type == TaskType::BACKGROUND) { 195 return false; 196 } else if (WillRunOnCurrentThread(type)) { 197 CancelableTask avatar(task); 198 task(); 199 return avatar.WaitUntilComplete(); 200 } 201 return PostTaskAndWait(std::move(task), type); 202 } 203 204 /** 205 * Post a cancelable task to the specified thread and wait until finished executing. 206 * Never allow to post a background synchronous task. 207 * 208 * @param task Task which need execution. 209 * @param type FrontendType of task, used to specify the thread. 210 * @return Returns 'true' whether task has been executed. 211 */ PostSyncTask(const CancelableTask & task,TaskType type)212 bool PostSyncTask(const CancelableTask& task, TaskType type) const 213 { 214 return PostSyncTask(CancelableTask(task), type); 215 } 216 217 virtual void AddTaskObserver(Task&& callback) = 0; 218 virtual void RemoveTaskObserver() = 0; 219 virtual bool WillRunOnCurrentThread(TaskType type) const = 0; 220 GetTid(TaskType type)221 virtual int32_t GetTid(TaskType type) 222 { 223 return 0; 224 } 225 GetTotalTaskNum(TaskType type)226 virtual uint32_t GetTotalTaskNum(TaskType type) 227 { 228 return 0; 229 } 230 231 protected: 232 TaskExecutor() = default; 233 234 virtual bool OnPostTask(Task&& task, TaskType type, uint32_t delayTime) const = 0; 235 virtual Task WrapTaskWithTraceId(Task&& task, int32_t id) const = 0; 236 237 #ifdef ACE_DEBUG OnPreSyncTask(TaskType type)238 virtual bool OnPreSyncTask(TaskType type) const 239 { 240 return true; 241 } OnPostSyncTask()242 virtual void OnPostSyncTask() const {} 243 #endif 244 245 private: 246 bool PostTaskAndWait(CancelableTask&& task, TaskType type, std::chrono::milliseconds timeoutMs = 0ms) const 247 { 248 #ifdef ACE_DEBUG 249 bool result = false; 250 if (OnPreSyncTask(type)) { 251 result = OnPostTask(Task(task), type, 0) && task.WaitUntilComplete(timeoutMs); 252 OnPostSyncTask(); 253 } 254 return result; 255 #else 256 return OnPostTask(Task(task), type, 0) && task.WaitUntilComplete(timeoutMs); 257 #endif 258 } 259 }; 260 261 class SingleTaskExecutor final { 262 public: 263 using Task = TaskExecutor::Task; 264 using CancelableTask = TaskExecutor::CancelableTask; 265 using TaskType = TaskExecutor::TaskType; 266 SingleTaskExecutor(RefPtr<TaskExecutor> && taskExecutor,TaskType type)267 SingleTaskExecutor(RefPtr<TaskExecutor>&& taskExecutor, TaskType type) 268 : taskExecutor_(std::move(taskExecutor)), type_(type) 269 {} SingleTaskExecutor(const RefPtr<TaskExecutor> & taskExecutor,TaskType type)270 SingleTaskExecutor(const RefPtr<TaskExecutor>& taskExecutor, TaskType type) 271 : taskExecutor_(taskExecutor), type_(type) 272 {} 273 ~SingleTaskExecutor() = default; 274 Make(RefPtr<TaskExecutor> && taskExecutor,TaskType type)275 static SingleTaskExecutor Make(RefPtr<TaskExecutor>&& taskExecutor, TaskType type) 276 { 277 return SingleTaskExecutor(std::move(taskExecutor), type); 278 } 279 Make(const RefPtr<TaskExecutor> & taskExecutor,TaskType type)280 static SingleTaskExecutor Make(const RefPtr<TaskExecutor>& taskExecutor, TaskType type) 281 { 282 return SingleTaskExecutor(taskExecutor, type); 283 } 284 285 /** 286 * Post a task to the specified thread. 287 * 288 * @param task Task which need execution. 289 * @return Returns 'true' whether task has been post successfully. 290 */ PostTask(Task && task)291 bool PostTask(Task&& task) const 292 { 293 return taskExecutor_ ? taskExecutor_->PostTask(std::move(task), type_) : false; 294 } 295 296 /** 297 * Post a task to the specified thread. 298 * 299 * @param task Task which need execution. 300 * @return Returns 'true' whether task has been post successfully. 301 */ PostTask(const Task & task)302 bool PostTask(const Task& task) const 303 { 304 return taskExecutor_ ? taskExecutor_->PostTask(task, type_) : false; 305 } 306 307 /** 308 * Post a delayed task to the specified thread. 309 * Never allow to post a background delayed task. 310 * 311 * @param task Task which need execution. 312 * @param delayTime Wait a period of time in milliseconds before execution. 313 * @return Returns 'true' if task has been posted successfully. 314 */ PostDelayedTask(Task && task,uint32_t delayTime)315 bool PostDelayedTask(Task&& task, uint32_t delayTime) const 316 { 317 return taskExecutor_ ? taskExecutor_->PostDelayedTask(std::move(task), type_, delayTime) : false; 318 } 319 320 /** 321 * Post a delayed task to the specified thread. 322 * Never allow to post a background delayed task. 323 * 324 * @param task Task which need execution. 325 * @param delayTime Wait a period of time in milliseconds before execution. 326 * @return Returns 'true' if task has been posted successfully. 327 */ PostDelayedTask(const Task & task,uint32_t delayTime)328 bool PostDelayedTask(const Task& task, uint32_t delayTime) const 329 { 330 return taskExecutor_ ? taskExecutor_->PostDelayedTask(task, type_, delayTime) : false; 331 } 332 333 /** 334 * Post a task to the specified thread and wait until finished executing. 335 * Never allow to post a background synchronous task. 336 * 337 * @param task Task which need execution. 338 * @return Returns 'true' whether task has been executed. 339 */ PostSyncTask(Task && task)340 bool PostSyncTask(Task&& task) const 341 { 342 return taskExecutor_ ? taskExecutor_->PostSyncTask(std::move(task), type_) : false; 343 } 344 345 /** 346 * Post a task to the specified thread and wait until finished executing. 347 * Never allow to post a background synchronous task. 348 * 349 * @param task Task which need execution. 350 * @return Returns 'true' whether task has been executed. 351 */ PostSyncTask(const Task & task)352 bool PostSyncTask(const Task& task) const 353 { 354 return taskExecutor_ ? taskExecutor_->PostSyncTask(task, type_) : false; 355 } 356 357 /** 358 * Post a cancelable task to the specified thread and wait until finished executing. 359 * Never allow to post a background synchronous task. 360 * 361 * @param task Task which need execution. 362 * @return Returns 'true' whether task has been executed. 363 */ PostSyncTask(CancelableTask && task)364 bool PostSyncTask(CancelableTask&& task) const 365 { 366 return taskExecutor_ ? taskExecutor_->PostSyncTask(std::move(task), type_) : false; 367 } 368 369 /** 370 * Post a cancelable task to the specified thread and wait until finished executing. 371 * Never allow to post a background synchronous task. 372 * 373 * @param task Task which need execution. 374 * @return Returns 'true' whether task has been executed. 375 */ PostSyncTask(const CancelableTask & task)376 bool PostSyncTask(const CancelableTask& task) const 377 { 378 return taskExecutor_ ? taskExecutor_->PostSyncTask(task, type_) : false; 379 } 380 GetTaskExecutor()381 RefPtr<TaskExecutor> GetTaskExecutor() const 382 { 383 return taskExecutor_; 384 } 385 IsRunOnCurrentThread()386 bool IsRunOnCurrentThread() const 387 { 388 return taskExecutor_ ? taskExecutor_->WillRunOnCurrentThread(type_) : false; 389 } 390 391 private: 392 RefPtr<TaskExecutor> taskExecutor_; 393 TaskExecutor::TaskType type_; 394 }; 395 396 } // namespace OHOS::Ace 397 398 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_THREAD_TASK_EXECUTOR_H 399