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 #include "base/log/log.h" 26 #include "base/utils/system_properties.h" 27 28 namespace OHOS::Ace { 29 30 // 1. Must be consistent with AppExecFwk::EventQueue::Priority. 31 // 2. Do not use this ability arbitrarily. 32 enum class PriorityType : int32_t { 33 // The highest priority queue, should be distributed until the tasks in the queue are completed. 34 VIP = 0, 35 // Event that should be distributed at once if possible. 36 IMMEDIATE, 37 // High priority event, sorted by handle time, should be distributed before low priority event. 38 HIGH, 39 // Normal event, sorted by handle time. 40 LOW, 41 // Event that should be distributed only if no other event right now. 42 IDLE, 43 }; 44 45 class TaskExecutor : public AceType { 46 DECLARE_ACE_TYPE(TaskExecutor, AceType); 47 ACE_DISALLOW_COPY_AND_MOVE(TaskExecutor); 48 49 public: 50 using Task = std::function<void()>; 51 using CancelableTask = CancelableCallback<void()>; 52 53 static constexpr int32_t TASK_TYPE_SIZE = 7; 54 enum class TaskType : uint32_t { 55 PLATFORM = 0, 56 UI, 57 IO, 58 GPU, 59 JS, 60 BACKGROUND, 61 UNKNOWN, 62 }; 63 64 ~TaskExecutor() override = default; 65 66 /** 67 * Post a task to the specified thread. 68 * 69 * @param task Task which need execution. 70 * @param type FrontendType of task, used to specify the thread. 71 * @param name Name of the task. 72 * @return Returns 'true' whether task has been post successfully. 73 */ 74 bool PostTask( 75 Task&& task, TaskType type, const std::string& name, PriorityType priorityType = PriorityType::LOW) const 76 { 77 return PostDelayedTask(std::move(task), type, 0, name, priorityType); 78 } 79 80 /** 81 * Post a task to the specified thread. 82 * 83 * @param task Task which need execution. 84 * @param type FrontendType of task, used to specify the thread. 85 * @param name Name of the task. 86 * @return Returns 'true' if task has been posted successfully. 87 */ 88 bool PostTask(const Task& task, TaskType type, const std::string& name, 89 PriorityType priorityType = PriorityType::LOW) const 90 { 91 return PostDelayedTask(task, type, 0, name, priorityType); 92 } 93 94 /** 95 * Post a task to the specified thread with a trace id. 96 * 97 * @param task Task which need execution. 98 * @param type FrontendType of task, used to specify the thread. 99 * @param id The id to trace the task. 100 * @param name Name of the task. 101 * @return Returns 'true' whether task has been post successfully. 102 */ PostTaskWithTraceId(Task && task,TaskType type,int32_t id,const std::string & name)103 bool PostTaskWithTraceId(Task&& task, TaskType type, int32_t id, const std::string& name) const 104 { 105 Task wrappedTask = WrapTaskWithTraceId(std::move(task), id); 106 return PostDelayedTask(std::move(wrappedTask), type, 0, name); 107 } 108 109 /** 110 * Post a task to the specified thread. 111 * 112 * @param task Task which need execution. 113 * @param type FrontendType of task, used to specify the thread. 114 * @param id The id to trace the task. 115 * @param name Name of the task. 116 * @return Returns 'true' if task has been posted successfully. 117 */ PostTaskWithTraceId(const Task & task,TaskType type,int32_t id,const std::string & name)118 bool PostTaskWithTraceId(const Task& task, TaskType type, int32_t id, const std::string& name) const 119 { 120 Task wrappedTask = WrapTaskWithTraceId(Task(task), id); 121 return PostDelayedTask(std::move(wrappedTask), type, 0, name); 122 } 123 124 /** 125 * Post a delayed task to the specified thread. 126 * Never allow to post a background delayed task. 127 * 128 * @param task Task which need execution. 129 * @param type FrontendType of task, used to specify the thread. 130 * @param delayTime Wait a period of time in milliseconds before execution. 131 * @param name Name of the task. 132 * @return Returns 'true' if task has been posted successfully. 133 */ 134 bool PostDelayedTask(Task&& task, TaskType type, uint32_t delayTime, const std::string& name, 135 PriorityType priorityType = PriorityType::LOW) const 136 { 137 if (delayTime > 0 && type == TaskType::BACKGROUND) { 138 return false; 139 } 140 return OnPostTask(std::move(task), type, delayTime, name, priorityType); 141 } 142 143 /** 144 * Post a delayed task to the specified thread. 145 * Never allow to post a background delayed task. 146 * 147 * @param task Task which need execution. 148 * @param type FrontendType of task, used to specify the thread. 149 * @param delayTime Wait a period of time in milliseconds before execution. 150 * @param name Name of the task. 151 * @return Returns 'true' if task has been posted successfully. 152 */ 153 bool PostDelayedTask(const Task& task, TaskType type, uint32_t delayTime, const std::string& name, 154 PriorityType priorityType = PriorityType::LOW) const 155 { 156 return PostDelayedTask(Task(task), type, delayTime, name, priorityType); 157 } 158 159 /** 160 * Post a task to the specified thread and wait until finished executing. 161 * Never allow to post a background synchronous task. 162 * 163 * @param task Task which need execution. 164 * @param type FrontendType of task, used to specify the thread. 165 * @param name Name of the task. 166 * @return Returns 'true' whether task has been executed. 167 */ 168 bool PostSyncTask( 169 Task&& task, TaskType type, const std::string& name, PriorityType priorityType = PriorityType::IMMEDIATE) const 170 { 171 if (!task || type == TaskType::BACKGROUND) { 172 return false; 173 } else if (WillRunOnCurrentThread(type)) { 174 task(); 175 return true; 176 } 177 return PostTaskAndWait(CancelableTask(std::move(task)), type, name, 0ms, priorityType); 178 } 179 180 /** 181 * Post a task to the specified thread and wait until finished executing. 182 * Never allow to post a background synchronous task. 183 * 184 * @param task Task which need execution. 185 * @param type FrontendType of task, used to specify the thread. 186 * @param timeoutMs Timeout in milliseconds before task execution. 187 * @param name Name of the task. 188 * @return Returns 'true' whether task has been executed. 189 */ PostSyncTaskTimeout(const Task & task,TaskType type,uint32_t timeoutMs,const std::string & name)190 bool PostSyncTaskTimeout(const Task& task, TaskType type, uint32_t timeoutMs, const std::string& name) const 191 { 192 if (!task || type == TaskType::BACKGROUND) { 193 return false; 194 } else if (WillRunOnCurrentThread(type)) { 195 task(); 196 return true; 197 } 198 return PostTaskAndWait( 199 CancelableTask(std::move(task)), type, name, std::chrono::milliseconds(timeoutMs)); 200 } 201 202 /** 203 * Post a task to the specified thread and wait until finished executing. 204 * Never allow to post a background synchronous task. 205 * 206 * @param task Task which need execution. 207 * @param type FrontendType of task, used to specify the thread. 208 * @param name Name of the task. 209 * @return Returns 'true' whether task has been executed. 210 */ PostSyncTask(const Task & task,TaskType type,const std::string & name)211 bool PostSyncTask(const Task& task, TaskType type, const std::string& name) const 212 { 213 return PostSyncTask(Task(task), type, name); 214 } 215 216 /** 217 * Post a cancelable task to the specified thread and wait until finished executing. 218 * Never allow to post a background synchronous task. 219 * 220 * @param task Task which need execution. 221 * @param type FrontendType of task, used to specify the thread. 222 * @param name Name of the task. 223 * @return Returns 'true' whether task has been executed. 224 */ PostSyncTask(CancelableTask && task,TaskType type,const std::string & name)225 bool PostSyncTask(CancelableTask&& task, TaskType type, const std::string& name) const 226 { 227 if (!task || type == TaskType::BACKGROUND) { 228 return false; 229 } else if (WillRunOnCurrentThread(type)) { 230 CancelableTask avatar(task); 231 task(); 232 return avatar.WaitUntilComplete(); 233 } 234 return PostTaskAndWait(std::move(task), type, name, 0ms); 235 } 236 237 /** 238 * Post a cancelable task to the specified thread and wait until finished executing. 239 * Never allow to post a background synchronous task. 240 * 241 * @param task Task which need execution. 242 * @param type FrontendType of task, used to specify the thread. 243 * @param name Name of the task. 244 * @return Returns 'true' whether task has been executed. 245 */ PostSyncTask(const CancelableTask & task,TaskType type,const std::string & name)246 bool PostSyncTask(const CancelableTask& task, TaskType type, const std::string& name) const 247 { 248 return PostSyncTask(CancelableTask(task), type, name); 249 } 250 251 /** 252 * The task use PostDelayedTask will new an object TraceId, when use 253 * RemoveTask will cause memory overflow. 254 * Post a delayed task without traceId to the specified thread. 255 * Never allow to post a background delayed task. 256 * 257 * @param task Task which need execution. 258 * @param type FrontendType of task, used to specify the thread. 259 * @param delayTime Wait a period of time in milliseconds before execution. 260 * @param name Name of the task. 261 * @return Returns 'true' if task has been posted successfully. 262 */ 263 bool PostDelayedTaskWithoutTraceId(Task&& task, TaskType type, uint32_t delayTime, const std::string& name, 264 PriorityType priorityType = PriorityType::LOW) const 265 { 266 if (delayTime > 0 && type == TaskType::BACKGROUND) { 267 return false; 268 } 269 return OnPostTaskWithoutTraceId(std::move(task), type, delayTime, name, priorityType); 270 } 271 272 virtual void AddTaskObserver(Task&& callback) = 0; 273 virtual void RemoveTaskObserver() = 0; 274 virtual bool WillRunOnCurrentThread(TaskType type) const = 0; 275 virtual void RemoveTask(TaskType type, const std::string &name) = 0; 276 GetTid(TaskType type)277 virtual int32_t GetTid(TaskType type) 278 { 279 return 0; 280 } 281 GetTotalTaskNum(TaskType type)282 virtual uint32_t GetTotalTaskNum(TaskType type) 283 { 284 return 0; 285 } 286 287 static PriorityType GetPriorityTypeWithCheck( 288 PriorityType priorityType, PriorityType defaultPriority = PriorityType::LOW) 289 { 290 // Temporary interface, used to control whether priority adjustment takes effect. 291 return SystemProperties::GetTaskPriorityAdjustmentEnable() ? priorityType : defaultPriority; 292 } 293 294 protected: 295 TaskExecutor() = default; 296 297 virtual bool OnPostTask(Task&& task, TaskType type, uint32_t delayTime, const std::string& name, 298 PriorityType priorityType = PriorityType::LOW) const = 0; 299 virtual Task WrapTaskWithTraceId(Task&& task, int32_t id) const = 0; 300 virtual bool OnPostTaskWithoutTraceId(Task&& task, TaskType type, uint32_t delayTime, const std::string& name, 301 PriorityType priorityType = PriorityType::LOW) const = 0; 302 303 #ifdef ACE_DEBUG OnPreSyncTask(TaskType type)304 virtual bool OnPreSyncTask(TaskType type) const 305 { 306 return true; 307 } OnPostSyncTask()308 virtual void OnPostSyncTask() const {} 309 #endif 310 311 private: 312 bool PostTaskAndWait(CancelableTask&& task, TaskType type, const std::string& name, 313 std::chrono::milliseconds timeoutMs = 0ms, PriorityType priorityType = PriorityType::IMMEDIATE) const 314 { 315 #ifdef ACE_DEBUG 316 bool result = false; 317 if (OnPreSyncTask(type)) { 318 result = OnPostTask(Task(task), type, 0, name, priorityType) && task.WaitUntilComplete(timeoutMs); 319 OnPostSyncTask(); 320 } 321 return result; 322 #else 323 return OnPostTask(Task(task), type, 0, name, priorityType) && task.WaitUntilComplete(timeoutMs); 324 #endif 325 } 326 }; 327 328 class TaskWrapper { 329 public: 330 virtual bool WillRunOnCurrentThread() = 0; 331 virtual void Call(const TaskExecutor::Task& task) = 0; Call(const TaskExecutor::Task & task,uint32_t delayTime)332 virtual void Call(const TaskExecutor::Task& task, uint32_t delayTime) {}; 333 334 virtual ~TaskWrapper() = default; 335 }; 336 337 class SingleTaskExecutor final { 338 public: 339 using Task = TaskExecutor::Task; 340 using CancelableTask = TaskExecutor::CancelableTask; 341 using TaskType = TaskExecutor::TaskType; 342 SingleTaskExecutor(RefPtr<TaskExecutor> && taskExecutor,TaskType type)343 SingleTaskExecutor(RefPtr<TaskExecutor>&& taskExecutor, TaskType type) 344 : taskExecutor_(std::move(taskExecutor)), type_(type) 345 {} SingleTaskExecutor(const RefPtr<TaskExecutor> & taskExecutor,TaskType type)346 SingleTaskExecutor(const RefPtr<TaskExecutor>& taskExecutor, TaskType type) 347 : taskExecutor_(taskExecutor), type_(type) 348 {} 349 ~SingleTaskExecutor() = default; 350 Make(RefPtr<TaskExecutor> && taskExecutor,TaskType type)351 static SingleTaskExecutor Make(RefPtr<TaskExecutor>&& taskExecutor, TaskType type) 352 { 353 return SingleTaskExecutor(std::move(taskExecutor), type); 354 } 355 Make(const RefPtr<TaskExecutor> & taskExecutor,TaskType type)356 static SingleTaskExecutor Make(const RefPtr<TaskExecutor>& taskExecutor, TaskType type) 357 { 358 return SingleTaskExecutor(taskExecutor, type); 359 } 360 361 /** 362 * Post a task to the specified thread. 363 * 364 * @param task Task which need execution. 365 * @param name Name of the task. 366 * @return Returns 'true' whether task has been post successfully. 367 */ PostTask(Task && task,const std::string & name)368 bool PostTask(Task&& task, const std::string& name) const 369 { 370 return taskExecutor_ ? taskExecutor_->PostTask(std::move(task), type_, name) : false; 371 } 372 373 /** 374 * Post a task to the specified thread with priority. 375 * 376 * @param task Task which need execution. 377 * @param name Name of the task. 378 * @param priorityType Priority of the task. 379 * @return Returns 'true' whether task has been post successfully. 380 */ PostTask(Task && task,const std::string & name,PriorityType priorityType)381 bool PostTask(Task&& task, const std::string& name, PriorityType priorityType) const 382 { 383 return taskExecutor_ ? taskExecutor_->PostTask(std::move(task), type_, name, priorityType) : false; 384 } 385 386 /** 387 * Post a task to the specified thread. 388 * 389 * @param task Task which need execution. 390 * @param name Name of the task. 391 * @return Returns 'true' whether task has been post successfully. 392 */ PostTask(const Task & task,const std::string & name)393 bool PostTask(const Task& task, const std::string& name) const 394 { 395 return taskExecutor_ ? taskExecutor_->PostTask(task, type_, name) : false; 396 } 397 398 /** 399 * Post a delayed task to the specified thread. 400 * Never allow to post a background delayed task. 401 * 402 * @param task Task which need execution. 403 * @param delayTime Wait a period of time in milliseconds before execution. 404 * @param name Name of the task. 405 * @return Returns 'true' if task has been posted successfully. 406 */ PostDelayedTask(Task && task,uint32_t delayTime,const std::string & name)407 bool PostDelayedTask(Task&& task, uint32_t delayTime, const std::string& name) const 408 { 409 return taskExecutor_ ? taskExecutor_->PostDelayedTask(std::move(task), type_, delayTime, name) : false; 410 } 411 412 /** 413 * Post a delayed task to the specified thread. 414 * Never allow to post a background delayed task. 415 * 416 * @param task Task which need execution. 417 * @param delayTime Wait a period of time in milliseconds before execution. 418 * @param name Name of the task. 419 * @return Returns 'true' if task has been posted successfully. 420 */ PostDelayedTask(const Task & task,uint32_t delayTime,const std::string & name)421 bool PostDelayedTask(const Task& task, uint32_t delayTime, const std::string& name) const 422 { 423 return taskExecutor_ ? taskExecutor_->PostDelayedTask(task, type_, delayTime, name) : false; 424 } 425 426 /** 427 * Post a task to the specified thread and wait until finished executing. 428 * Never allow to post a background synchronous task. 429 * 430 * @param task Task which need execution. 431 * @param name Name of the task. 432 * @return Returns 'true' whether task has been executed. 433 */ PostSyncTask(Task && task,const std::string & name)434 bool PostSyncTask(Task&& task, const std::string& name) const 435 { 436 return taskExecutor_ ? taskExecutor_->PostSyncTask(std::move(task), type_, name) : false; 437 } 438 439 /** 440 * Post a task to the specified thread and wait until finished executing. 441 * Never allow to post a background synchronous task. 442 * 443 * @param task Task which need execution. 444 * @param name Name of the task. 445 * @return Returns 'true' whether task has been executed. 446 */ PostSyncTask(const Task & task,const std::string & name)447 bool PostSyncTask(const Task& task, const std::string& name) const 448 { 449 return taskExecutor_ ? taskExecutor_->PostSyncTask(task, type_, name) : false; 450 } 451 452 /** 453 * Post a cancelable task to the specified thread and wait until finished executing. 454 * Never allow to post a background synchronous task. 455 * 456 * @param task Task which need execution. 457 * @param name Name of the task. 458 * @return Returns 'true' whether task has been executed. 459 */ PostSyncTask(CancelableTask && task,const std::string & name)460 bool PostSyncTask(CancelableTask&& task, const std::string& name) const 461 { 462 return taskExecutor_ ? taskExecutor_->PostSyncTask(std::move(task), type_, name) : false; 463 } 464 465 /** 466 * Post a cancelable task to the specified thread and wait until finished executing. 467 * Never allow to post a background synchronous task. 468 * 469 * @param task Task which need execution. 470 * @param name Name of the task. 471 * @return Returns 'true' whether task has been executed. 472 */ PostSyncTask(const CancelableTask & task,const std::string & name)473 bool PostSyncTask(const CancelableTask& task, const std::string& name) const 474 { 475 return taskExecutor_ ? taskExecutor_->PostSyncTask(task, type_, name) : false; 476 } 477 GetTaskExecutor()478 RefPtr<TaskExecutor> GetTaskExecutor() const 479 { 480 return taskExecutor_; 481 } 482 IsRunOnCurrentThread()483 bool IsRunOnCurrentThread() const 484 { 485 return taskExecutor_ ? taskExecutor_->WillRunOnCurrentThread(type_) : false; 486 } 487 488 private: 489 RefPtr<TaskExecutor> taskExecutor_; 490 TaskExecutor::TaskType type_; 491 }; 492 493 } // namespace OHOS::Ace 494 495 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_THREAD_TASK_EXECUTOR_H 496