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 "hc_task_thread.h"
17 #include "hal_error.h"
18 #include "hc_log.h"
19
20 #define TASK_ALLOC_UINT 5
21
IMPLEMENT_HC_VECTOR(TaskVec,HcTaskWrap,TASK_ALLOC_UINT)22 IMPLEMENT_HC_VECTOR(TaskVec, HcTaskWrap, TASK_ALLOC_UINT)
23
24 static HcTaskBase* PopTask(HcTaskThread* thread)
25 {
26 if (thread == NULL) {
27 return NULL;
28 }
29
30 thread->queueLock.lock(&thread->queueLock);
31 HcTaskWrap task;
32 HcBool ret = thread->tasks.popFront(&thread->tasks, &task);
33 thread->queueLock.unlock(&thread->queueLock);
34 if (ret) {
35 return task.task;
36 }
37 return NULL;
38 }
39
PushTask(struct HcTaskThreadT * thread,HcTaskBase * task)40 static void PushTask(struct HcTaskThreadT* thread, HcTaskBase* task)
41 {
42 if (thread == NULL || task == NULL) {
43 return;
44 }
45
46 thread->queueLock.lock(&thread->queueLock);
47 HcTaskWrap taskWarp;
48 taskWarp.task = task;
49 thread->tasks.pushBack(&thread->tasks, &taskWarp);
50 thread->thread.notify(&thread->thread);
51 thread->queueLock.unlock(&thread->queueLock);
52 }
53
Clear(struct HcTaskThreadT * thread)54 static void Clear(struct HcTaskThreadT* thread)
55 {
56 thread->queueLock.lock(&thread->queueLock);
57 HcTaskWrap *taskWarp = NULL;
58 uint32_t index;
59 FOR_EACH_HC_VECTOR(thread->tasks, index, taskWarp) {
60 if (taskWarp->task->destroy) {
61 taskWarp->task->destroy(taskWarp->task);
62 }
63 HcFree(taskWarp->task);
64 }
65 thread->tasks.clear(&thread->tasks);
66 thread->queueLock.unlock(&thread->queueLock);
67 }
68
StopAndClear(struct HcTaskThreadT * thread)69 static void StopAndClear(struct HcTaskThreadT* thread)
70 {
71 if (thread == NULL) {
72 return;
73 }
74 thread->clear(thread);
75 thread->quit = HC_TRUE;
76 thread->thread.notify(&thread->thread);
77 thread->thread.join(&thread->thread);
78 }
79
StartTaskThread(struct HcTaskThreadT * thread)80 static int32_t StartTaskThread(struct HcTaskThreadT* thread)
81 {
82 if (thread == NULL) {
83 return HAL_ERR_BAD_ALLOC;
84 }
85
86 thread->quit = HC_FALSE;
87 int32_t res = thread->thread.start(&thread->thread);
88 if (res != HAL_SUCCESS) {
89 LOGE("Start thread failed, res:%d", res);
90 }
91 return res;
92 }
93
TaskThreadLoop(void * args)94 static int TaskThreadLoop(void* args)
95 {
96 HcTaskThread* thread = (HcTaskThread*)args;
97 if (thread == NULL) {
98 return -1;
99 }
100
101 while (1) {
102 if (thread->quit) {
103 break;
104 }
105 HcTaskBase* task = PopTask(thread);
106 if (task != NULL) {
107 if (task->doAction) {
108 task->doAction(task);
109 }
110 if (task->destroy) {
111 task->destroy(task);
112 }
113 HcFree(task);
114 } else {
115 thread->thread.wait(&thread->thread);
116 }
117 }
118 return 0;
119 }
120
InitHcTaskThread(HcTaskThread * thread,size_t stackSize,const char * threadName)121 int32_t InitHcTaskThread(HcTaskThread* thread, size_t stackSize, const char* threadName)
122 {
123 if (thread == NULL) {
124 return -1;
125 }
126
127 thread->pushTask = PushTask;
128 thread->startThread = StartTaskThread;
129 thread->clear = Clear;
130 thread->stopAndClear = StopAndClear;
131 int32_t res = InitThread(&thread->thread, TaskThreadLoop, stackSize, threadName);
132 if (res != 0) {
133 return res;
134 }
135 res = InitHcMutex(&thread->queueLock);
136 if (res != 0) {
137 DestroyThread(&thread->thread);
138 return res;
139 }
140 thread->tasks = CREATE_HC_VECTOR(TaskVec);
141 return 0;
142 }
143
DestroyHcTaskThread(HcTaskThread * thread)144 void DestroyHcTaskThread(HcTaskThread* thread)
145 {
146 DESTROY_HC_VECTOR(TaskVec, &thread->tasks);
147 DestroyHcMutex(&thread->queueLock);
148 DestroyThread(&thread->thread);
149 }