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_condition.h"
17 
18 #include "hc_log.h"
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
Wait(pthread_cond_t * cond,HcMutex * mutex)24 int Wait(pthread_cond_t* cond, HcMutex* mutex)
25 {
26     if (cond == NULL || mutex == NULL) {
27         return -1;
28     }
29     int res = pthread_cond_wait(cond, &mutex->mutex);
30     if (res != 0) {
31         LOGE("[OS]: pthread_cond_wait fail. [Res]: %d", res);
32     }
33     return res;
34 }
35 
Notify(pthread_cond_t * cond)36 void Notify(pthread_cond_t* cond)
37 {
38     if (cond == NULL) {
39         return;
40     }
41     int res = pthread_cond_signal(cond);
42     if (res != 0) {
43         LOGW("[OS]: pthread_cond_wait fail. [Res]: %d", res);
44     }
45 }
46 
HcCondWaitWithoutLock(struct HcConditionT * hcCond)47 int HcCondWaitWithoutLock(struct HcConditionT* hcCond)
48 {
49     if (hcCond == NULL || hcCond->mutex == NULL) {
50         return -1;
51     }
52     if (hcCond->notified) {
53         hcCond->notified = HC_FALSE;
54         return 0;
55     } else {
56         int ret;
57         hcCond->waited = HC_TRUE;
58         ret = Wait(&hcCond->cond, hcCond->mutex);
59         hcCond->waited = HC_FALSE;
60         hcCond->notified = HC_FALSE;
61         return ret;
62     }
63 }
64 
HcCondNotifyWithoutLock(struct HcConditionT * hcCond)65 void HcCondNotifyWithoutLock(struct HcConditionT* hcCond)
66 {
67     if (hcCond == NULL || hcCond->mutex == NULL) {
68         return;
69     }
70 
71     if (!hcCond->waited) {
72         hcCond->notified = HC_TRUE;
73     } else {
74         hcCond->notified = HC_FALSE;
75     }
76     Notify(&hcCond->cond);
77 }
78 
HcCondWait(struct HcConditionT * hcCond)79 int HcCondWait(struct HcConditionT* hcCond)
80 {
81     if (hcCond == NULL) {
82         return -1;
83     }
84     if (hcCond->mutex == NULL) {
85         return -1;
86     }
87 
88     hcCond->mutex->lock(hcCond->mutex);
89     if (hcCond->notified) {
90         hcCond->notified = HC_FALSE;
91         hcCond->mutex->unlock(hcCond->mutex);
92         return 0;
93     } else {
94         int ret;
95         hcCond->waited = HC_TRUE;
96         ret = Wait(&hcCond->cond, hcCond->mutex);
97         hcCond->waited = HC_FALSE;
98         hcCond->notified = HC_FALSE;
99         hcCond->mutex->unlock(hcCond->mutex);
100         return ret;
101     }
102 }
103 
HcCondNotify(struct HcConditionT * hcCond)104 void HcCondNotify(struct HcConditionT* hcCond)
105 {
106     if (hcCond == NULL || hcCond->mutex == NULL) {
107         return;
108     }
109 
110     hcCond->mutex->lock(hcCond->mutex);
111 
112     if (!hcCond->waited) {
113         hcCond->notified = HC_TRUE;
114     } else {
115         hcCond->notified = HC_FALSE;
116     }
117     Notify(&hcCond->cond);
118     hcCond->mutex->unlock(hcCond->mutex);
119 }
120 
InitHcCond(HcCondition * hcCond,HcMutex * mutex)121 int32_t InitHcCond(HcCondition* hcCond, HcMutex* mutex)
122 {
123     if (hcCond == NULL) {
124         return -1;
125     }
126     hcCond->notified = HC_FALSE;
127     hcCond->waited = HC_FALSE;
128     hcCond->wait = HcCondWait;
129     hcCond->notify = HcCondNotify;
130     hcCond->waitWithoutLock = HcCondWaitWithoutLock;
131     hcCond->notifyWithoutLock = HcCondNotifyWithoutLock;
132 
133     pthread_condattr_t attr;
134     pthread_condattr_init(&attr);
135     int res = pthread_cond_init(&hcCond->cond, &attr);
136     pthread_condattr_destroy(&attr);
137     if (res != 0) {
138         LOGE("[OS]: pthread_cond_init fail. [Res]: %d", res);
139         return -1;
140     }
141 
142     if (mutex != NULL) {
143         hcCond->mutex = mutex;
144         hcCond->innerMutex = HC_FALSE;
145     } else {
146         hcCond->mutex = (HcMutex*)HcMalloc(sizeof(HcMutex), 0);
147         if (hcCond->mutex != NULL) {
148             res = InitHcMutex(hcCond->mutex);
149             if (res != 0) {
150                 HcFree(hcCond->mutex);
151                 hcCond->mutex = NULL;
152                 return res;
153             }
154             hcCond->innerMutex = HC_TRUE;
155         } else {
156             return -1;
157         }
158     }
159     return 0;
160 }
161 
DestroyHcCond(HcCondition * hcCond)162 void DestroyHcCond(HcCondition* hcCond)
163 {
164     if (hcCond == NULL) {
165         return;
166     }
167 
168     if (hcCond->innerMutex && hcCond->mutex) {
169         DestroyHcMutex(hcCond->mutex);
170         HcFree(hcCond->mutex);
171         hcCond->mutex = NULL;
172     }
173     int res = pthread_cond_destroy(&hcCond->cond);
174     if (res != 0) {
175         LOGW("[OS]: pthread_cond_destroy fail. [Res]: %d", res);
176     }
177 }
178 
179 #ifdef __cplusplus
180 }
181 #endif