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 #include "async_task_manager.h"
17 #include "ace_log.h"
18 #include "fatal_handler.h"
19
20 #if (defined(__LINUX__) || defined(__LITEOS_A__))
21 #define TRY_LOCK() \
22 { \
23 pthread_mutex_lock(&lock_); \
24 }
25
26 #define TRY_UNLOCK() \
27 { \
28 pthread_mutex_unlock(&lock_); \
29 }
30 #elif defined(__LITEOS_M__)
31 #define TRY_LOCK() \
32 { \
33 LOS_TaskLock(); \
34 }
35 #define TRY_UNLOCK() \
36 { \
37 LOS_TaskUnlock(); \
38 }
39 #else
40 #define TRY_LOCK() \
41 { \
42 }
43 #define TRY_UNLOCK() \
44 { \
45 }
46 #endif
47
48 namespace OHOS {
49 namespace ACELite {
AsyncTaskManager()50 AsyncTaskManager::AsyncTaskManager()
51 : head_(nullptr),
52 tail_(nullptr),
53 #if (defined(__LINUX__) || defined(__LITEOS_A__))
54 lock_(PTHREAD_MUTEX_INITIALIZER),
55 #endif
56 uniqueTaskID_(0),
57 front_(false),
58 initialized_(false)
59 {
60 #if (defined(__LINUX__) || defined(__LITEOS_A__))
61 pthread_mutex_init(&lock_, nullptr);
62 #endif
63 }
64
Reset()65 void AsyncTaskManager::Reset()
66 {
67 while (head_ != nullptr) {
68 AsyncTask *task = head_;
69 head_ = head_->next;
70 delete task;
71 task = nullptr;
72 }
73 tail_ = nullptr;
74 }
75
GetInstance()76 AsyncTaskManager &AsyncTaskManager::GetInstance()
77 {
78 static AsyncTaskManager instance;
79 return instance;
80 }
81
Init()82 void AsyncTaskManager::Init()
83 {
84 Reset(); // make sure no residual task in list
85 if (initialized_) {
86 // do not add repeatly
87 return;
88 }
89 Task::Init();
90 initialized_ = true;
91 }
92
Callback()93 void AsyncTaskManager::Callback()
94 {
95 if (!front_) {
96 return;
97 }
98
99 while (head_ != nullptr) {
100 AsyncTask *task = head_;
101 task->isRunning = true;
102 task->handler(task->data);
103 if (head_ == tail_) {
104 tail_ = nullptr;
105 }
106 head_ = head_->next;
107 delete task;
108 task = nullptr;
109 }
110 }
111
Dispatch(AsyncTaskHandler handler,void * data,const void * context)112 uint16_t AsyncTaskManager::Dispatch(AsyncTaskHandler handler, void *data, const void *context)
113 {
114 if (handler == nullptr) {
115 HILOG_ERROR(HILOG_MODULE_ACE, "AsyncTaskManager::Dispatch failed: handler is null.");
116 return DISPATCH_FAILURE;
117 }
118 if (FatalHandler::GetInstance().IsFatalErrorHitted()) {
119 HILOG_ERROR(HILOG_MODULE_ACE, "AsyncTaskManager::Dispatch failed: Fatal error is hitted.");
120 return DISPATCH_FAILURE;
121 }
122 TRY_LOCK();
123 auto *task = new AsyncTask();
124 if (task == nullptr) {
125 HILOG_ERROR(HILOG_MODULE_ACE, "AsyncTaskManager::Dispatch failed: out of memory.");
126 TRY_UNLOCK();
127 return DISPATCH_FAILURE;
128 }
129 task->handler = handler;
130 task->data = data;
131 ++uniqueTaskID_;
132 //溢出为0,造成page切换失败
133 if (uniqueTaskID_ == 0) {
134 uniqueTaskID_ += 1;
135 }
136 task->id = (uniqueTaskID_);
137 task->context = context;
138 task->isRunning = false;
139 task->next = nullptr;
140 if (head_ == nullptr) {
141 head_ = task;
142 tail_ = task;
143 } else {
144 tail_->next = task;
145 tail_ = task;
146 }
147 TRY_UNLOCK();
148 return uniqueTaskID_;
149 }
150
Cancel(uint16_t taskID)151 void AsyncTaskManager::Cancel(uint16_t taskID)
152 {
153 if (DISPATCH_FAILURE == taskID) {
154 HILOG_ERROR(HILOG_MODULE_ACE, "AsyncTaskManager::Cancel failed: invalid task ID.");
155 return;
156 }
157 TRY_LOCK();
158 AsyncTask *node = head_;
159 AsyncTask *prev = nullptr;
160 while (node != nullptr) {
161 if (node->id == taskID && !(node->isRunning)) {
162 if (prev == nullptr) {
163 head_ = head_->next;
164 } else {
165 prev->next = node->next;
166 if (node == tail_) {
167 tail_ = prev;
168 }
169 }
170 delete node;
171 node = nullptr;
172 break;
173 }
174 prev = node;
175 node = node->next;
176 }
177 TRY_UNLOCK();
178 }
179
CancelWithContext(const void * context)180 void AsyncTaskManager::CancelWithContext(const void *context)
181 {
182 if (context == nullptr) {
183 HILOG_ERROR(HILOG_MODULE_ACE, "AsyncTaskManager::CancelWithContext failed: null context.");
184 return;
185 }
186 TRY_LOCK();
187 AsyncTask *node = head_;
188 AsyncTask *prev = nullptr;
189 AsyncTask *next = nullptr;
190 while (node != nullptr) {
191 next = node->next;
192 if ((node->context == context) && !(node->isRunning)) {
193 if (prev == nullptr) {
194 head_ = head_->next;
195 } else {
196 prev->next = next;
197 }
198 if (node == tail_) {
199 tail_ = prev;
200 }
201 delete node;
202 node = next;
203 continue;
204 }
205 prev = node;
206 node = next;
207 }
208 TRY_UNLOCK();
209 }
210
SetFront(bool front)211 void AsyncTaskManager::SetFront(bool front)
212 {
213 front_ = front;
214 }
215 } // namespace ACELite
216 } // namespace OHOS
217