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