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 task->id = (++uniqueTaskID_);
132 task->context = context;
133 task->isRunning = false;
134 task->next = nullptr;
135 if (head_ == nullptr) {
136 head_ = task;
137 tail_ = task;
138 } else {
139 tail_->next = task;
140 tail_ = task;
141 }
142 TRY_UNLOCK();
143 return uniqueTaskID_;
144 }
145
Cancel(uint16_t taskID)146 void AsyncTaskManager::Cancel(uint16_t taskID)
147 {
148 if (DISPATCH_FAILURE == taskID) {
149 HILOG_ERROR(HILOG_MODULE_ACE, "AsyncTaskManager::Cancel failed: invalid task ID.");
150 return;
151 }
152 TRY_LOCK();
153 AsyncTask *node = head_;
154 AsyncTask *prev = nullptr;
155 while (node != nullptr) {
156 if (node->id == taskID && !(node->isRunning)) {
157 if (prev == nullptr) {
158 head_ = head_->next;
159 } else {
160 prev->next = node->next;
161 if (node == tail_) {
162 tail_ = prev;
163 }
164 }
165 delete node;
166 node = nullptr;
167 break;
168 }
169 prev = node;
170 node = node->next;
171 }
172 TRY_UNLOCK();
173 }
174
CancelWithContext(const void * context)175 void AsyncTaskManager::CancelWithContext(const void *context)
176 {
177 if (context == nullptr) {
178 HILOG_ERROR(HILOG_MODULE_ACE, "AsyncTaskManager::CancelWithContext failed: null context.");
179 return;
180 }
181 TRY_LOCK();
182 AsyncTask *node = head_;
183 AsyncTask *prev = nullptr;
184 AsyncTask *next = nullptr;
185 while (node != nullptr) {
186 next = node->next;
187 if ((node->context == context) && !(node->isRunning)) {
188 if (prev == nullptr) {
189 head_ = head_->next;
190 } else {
191 prev->next = next;
192 }
193 if (node == tail_) {
194 tail_ = prev;
195 }
196 delete node;
197 node = next;
198 continue;
199 }
200 prev = node;
201 node = next;
202 }
203 TRY_UNLOCK();
204 }
205
SetFront(bool front)206 void AsyncTaskManager::SetFront(bool front)
207 {
208 front_ = front;
209 }
210 } // namespace ACELite
211 } // namespace OHOS
212