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 (void)LockHcMutex(&thread->queueLock);
31 HcTaskWrap task;
32 HcBool ret = thread->tasks.popFront(&thread->tasks, &task);
33 UnlockHcMutex(&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 (void)LockHcMutex(&thread->queueLock);
47 HcTaskWrap taskWarp;
48 taskWarp.task = task;
49 thread->tasks.pushBack(&thread->tasks, &taskWarp);
50 thread->thread.notify(&thread->thread);
51 UnlockHcMutex(&thread->queueLock);
52 }
53
Clear(struct HcTaskThreadT * thread)54 static void Clear(struct HcTaskThreadT* thread)
55 {
56 (void)LockHcMutex(&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 UnlockHcMutex(&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:%" LOG_PUB "d", res);
90 }
91 return res;
92 }
93
TaskThreadLoop(void * args)94 static int TaskThreadLoop(void* args)
95 {
96 LOGI("start task loop.");
97 HcTaskThread* thread = (HcTaskThread*)args;
98 if (thread == NULL) {
99 LOGE("thread is null!");
100 return -1;
101 }
102
103 while (1) {
104 if (thread->quit) {
105 LOGW("thread quit!");
106 break;
107 }
108 HcTaskBase* task = PopTask(thread);
109 if (task != NULL) {
110 if (task->doAction) {
111 task->doAction(task);
112 }
113 if (task->destroy) {
114 task->destroy(task);
115 }
116 HcFree(task);
117 } else {
118 thread->thread.wait(&thread->thread);
119 }
120 }
121 return 0;
122 }
123
InitHcTaskThread(HcTaskThread * thread,size_t stackSize,const char * threadName)124 int32_t InitHcTaskThread(HcTaskThread* thread, size_t stackSize, const char* threadName)
125 {
126 if (thread == NULL) {
127 return -1;
128 }
129
130 thread->pushTask = PushTask;
131 thread->startThread = StartTaskThread;
132 thread->clear = Clear;
133 thread->stopAndClear = StopAndClear;
134 int32_t res = InitThread(&thread->thread, TaskThreadLoop, stackSize, threadName);
135 if (res != 0) {
136 return res;
137 }
138 res = InitHcMutex(&thread->queueLock, false);
139 if (res != 0) {
140 DestroyThread(&thread->thread);
141 return res;
142 }
143 thread->tasks = CREATE_HC_VECTOR(TaskVec);
144 return 0;
145 }
146
DestroyHcTaskThread(HcTaskThread * thread)147 void DestroyHcTaskThread(HcTaskThread* thread)
148 {
149 DESTROY_HC_VECTOR(TaskVec, &thread->tasks);
150 DestroyHcMutex(&thread->queueLock);
151 DestroyThread(&thread->thread);
152 }