• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }