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; Destory()220 virtual void Destory() {} 221 GetTid(TaskType type)222 virtual int32_t GetTid(TaskType type) 223 { 224 return 0; 225 } 226 GetTotalTaskNum(TaskType type)227 virtual uint32_t GetTotalTaskNum(TaskType type) 228 { 229 return 0; 230 } 231 232 protected: 233 TaskExecutor() = default; 234 235 virtual bool OnPostTask(Task&& task, TaskType type, uint32_t delayTime) const = 0; 236 virtual Task WrapTaskWithTraceId(Task&& task, int32_t id) const = 0; 237 238 #ifdef ACE_DEBUG OnPreSyncTask(TaskType type)239 virtual bool OnPreSyncTask(TaskType type) const 240 { 241 return true; 242 } OnPostSyncTask()243 virtual void OnPostSyncTask() const {} 244 #endif 245 246 private: 247 bool PostTaskAndWait(CancelableTask&& task, TaskType type, std::chrono::milliseconds timeoutMs = 0ms) const 248 { 249 #ifdef ACE_DEBUG 250 bool result = false; 251 if (OnPreSyncTask(type)) { 252 result = OnPostTask(Task(task), type, 0) && task.WaitUntilComplete(timeoutMs); 253 OnPostSyncTask(); 254 } 255 return result; 256 #else 257 return OnPostTask(Task(task), type, 0) && task.WaitUntilComplete(timeoutMs); 258 #endif 259 } 260 }; 261 262 class SingleTaskExecutor final { 263 public: 264 using Task = TaskExecutor::Task; 265 using CancelableTask = TaskExecutor::CancelableTask; 266 using TaskType = TaskExecutor::TaskType; 267 SingleTaskExecutor(RefPtr<TaskExecutor> && taskExecutor,TaskType type)268 SingleTaskExecutor(RefPtr<TaskExecutor>&& taskExecutor, TaskType type) 269 : taskExecutor_(std::move(taskExecutor)), type_(type) 270 {} SingleTaskExecutor(const RefPtr<TaskExecutor> & taskExecutor,TaskType type)271 SingleTaskExecutor(const RefPtr<TaskExecutor>& taskExecutor, TaskType type) 272 : taskExecutor_(taskExecutor), type_(type) 273 {} 274 ~SingleTaskExecutor() = default; 275 Make(RefPtr<TaskExecutor> && taskExecutor,TaskType type)276 static SingleTaskExecutor Make(RefPtr<TaskExecutor>&& taskExecutor, TaskType type) 277 { 278 return SingleTaskExecutor(std::move(taskExecutor), type); 279 } 280 Make(const RefPtr<TaskExecutor> & taskExecutor,TaskType type)281 static SingleTaskExecutor Make(const RefPtr<TaskExecutor>& taskExecutor, TaskType type) 282 { 283 return SingleTaskExecutor(taskExecutor, type); 284 } 285 286 /** 287 * Post a task to the specified thread. 288 * 289 * @param task Task which need execution. 290 * @return Returns 'true' whether task has been post successfully. 291 */ PostTask(Task && task)292 bool PostTask(Task&& task) const 293 { 294 return taskExecutor_ ? taskExecutor_->PostTask(std::move(task), type_) : false; 295 } 296 297 /** 298 * Post a task to the specified thread. 299 * 300 * @param task Task which need execution. 301 * @return Returns 'true' whether task has been post successfully. 302 */ PostTask(const Task & task)303 bool PostTask(const Task& task) const 304 { 305 return taskExecutor_ ? taskExecutor_->PostTask(task, type_) : false; 306 } 307 308 /** 309 * Post a delayed task to the specified thread. 310 * Never allow to post a background delayed task. 311 * 312 * @param task Task which need execution. 313 * @param delayTime Wait a period of time in milliseconds before execution. 314 * @return Returns 'true' if task has been posted successfully. 315 */ PostDelayedTask(Task && task,uint32_t delayTime)316 bool PostDelayedTask(Task&& task, uint32_t delayTime) const 317 { 318 return taskExecutor_ ? taskExecutor_->PostDelayedTask(std::move(task), type_, delayTime) : false; 319 } 320 321 /** 322 * Post a delayed task to the specified thread. 323 * Never allow to post a background delayed task. 324 * 325 * @param task Task which need execution. 326 * @param delayTime Wait a period of time in milliseconds before execution. 327 * @return Returns 'true' if task has been posted successfully. 328 */ PostDelayedTask(const Task & task,uint32_t delayTime)329 bool PostDelayedTask(const Task& task, uint32_t delayTime) const 330 { 331 return taskExecutor_ ? taskExecutor_->PostDelayedTask(task, type_, delayTime) : false; 332 } 333 334 /** 335 * Post a task to the specified thread and wait until finished executing. 336 * Never allow to post a background synchronous task. 337 * 338 * @param task Task which need execution. 339 * @return Returns 'true' whether task has been executed. 340 */ PostSyncTask(Task && task)341 bool PostSyncTask(Task&& task) const 342 { 343 return taskExecutor_ ? taskExecutor_->PostSyncTask(std::move(task), type_) : false; 344 } 345 346 /** 347 * Post a task to the specified thread and wait until finished executing. 348 * Never allow to post a background synchronous task. 349 * 350 * @param task Task which need execution. 351 * @return Returns 'true' whether task has been executed. 352 */ PostSyncTask(const Task & task)353 bool PostSyncTask(const Task& task) const 354 { 355 return taskExecutor_ ? taskExecutor_->PostSyncTask(task, type_) : false; 356 } 357 358 /** 359 * Post a cancelable task to the specified thread and wait until finished executing. 360 * Never allow to post a background synchronous task. 361 * 362 * @param task Task which need execution. 363 * @return Returns 'true' whether task has been executed. 364 */ PostSyncTask(CancelableTask && task)365 bool PostSyncTask(CancelableTask&& task) const 366 { 367 return taskExecutor_ ? taskExecutor_->PostSyncTask(std::move(task), type_) : false; 368 } 369 370 /** 371 * Post a cancelable task to the specified thread and wait until finished executing. 372 * Never allow to post a background synchronous task. 373 * 374 * @param task Task which need execution. 375 * @return Returns 'true' whether task has been executed. 376 */ PostSyncTask(const CancelableTask & task)377 bool PostSyncTask(const CancelableTask& task) const 378 { 379 return taskExecutor_ ? taskExecutor_->PostSyncTask(task, type_) : false; 380 } 381 GetTaskExecutor()382 RefPtr<TaskExecutor> GetTaskExecutor() const 383 { 384 return taskExecutor_; 385 } 386 IsRunOnCurrentThread()387 bool IsRunOnCurrentThread() const 388 { 389 return taskExecutor_ ? taskExecutor_->WillRunOnCurrentThread(type_) : false; 390 } 391 392 private: 393 RefPtr<TaskExecutor> taskExecutor_; 394 TaskExecutor::TaskType type_; 395 }; 396 397 } // namespace OHOS::Ace 398 399 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_THREAD_TASK_EXECUTOR_H 400