• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 #define HST_LOG_TAG "ConditionVariable"
17 
18 #include "osal/task/condition_variable.h"
19 #include <ratio>
20 #include <ctime>
21 #include "common/log.h"
22 
23 namespace {
TmToNs(struct timespec tm)24 inline long long TmToNs(struct timespec tm)
25 {
26     return tm.tv_sec * std::giga::num + tm.tv_nsec;
27 }
28 
NsToTm(long long ns)29 inline struct timespec NsToTm(long long ns)
30 {
31     return {ns / std::giga::num, static_cast<long>(ns % std::giga::num)};
32 }
33 }
34 
35 namespace OHOS {
36 namespace Media {
ConditionVariable()37 ConditionVariable::ConditionVariable() noexcept : condInited_(true)
38 {
39     pthread_condattr_t attr;
40     pthread_condattr_init(&attr);
41 #ifndef __LITEOS_M__
42 #ifdef USING_CLOCK_REALTIME
43     pthread_condattr_setclock(&attr, CLOCK_REALTIME);
44 #else
45     pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
46 #endif
47 #endif
48     int rtv = pthread_cond_init(&cond_, &attr);
49     if (rtv != 0) {
50         condInited_ = false;
51         MEDIA_LOG_E("failed to init pthread cond variable");
52     }
53     pthread_condattr_destroy(&attr);
54 }
55 
~ConditionVariable()56 ConditionVariable::~ConditionVariable() noexcept
57 {
58     if (condInited_) {
59         pthread_cond_destroy(&cond_);
60     }
61 }
62 
NotifyOne()63 void ConditionVariable::NotifyOne() noexcept
64 {
65     if (!condInited_) {
66         MEDIA_LOG_E("NotifyOne uninitialized pthread cond");
67         return;
68     }
69     int ret = pthread_cond_signal(&cond_);
70     if (ret != 0) {
71         MEDIA_LOG_E("NotifyOne failed with errno = " PUBLIC_LOG_D32, ret);
72     }
73 }
74 
NotifyAll()75 void ConditionVariable::NotifyAll() noexcept
76 {
77     if (!condInited_) {
78         MEDIA_LOG_E("NotifyAll uninitialized pthread cond");
79         return;
80     }
81     int ret = pthread_cond_broadcast(&cond_);
82     if (ret != 0) {
83         MEDIA_LOG_E("NotifyAll failed with errno = " PUBLIC_LOG_D32, ret);
84     }
85 }
86 
Wait(AutoLock & lock)87 void ConditionVariable::Wait(AutoLock& lock) noexcept
88 {
89     if (!condInited_) {
90         MEDIA_LOG_E("Wait uninitialized pthread cond");
91         return;
92     }
93     pthread_cond_wait(&cond_, &(lock.mutex_->nativeHandle_));
94 }
95 
Wait(AutoLock & lock,std::function<bool ()> pred)96 void ConditionVariable::Wait(AutoLock& lock, std::function<bool()> pred) noexcept
97 {
98     if (!condInited_) {
99         MEDIA_LOG_E("Wait uninitialized pthread cond");
100         return;
101     }
102     while (!pred()) {
103         Wait(lock);
104     }
105 }
106 
WaitFor(AutoLock & lock,int timeoutMs)107 bool ConditionVariable::WaitFor(AutoLock& lock, int timeoutMs)
108 {
109     if (timeoutMs < 0) {
110         MEDIA_LOG_E("ConditionVariable WaitUntil invalid timeoutMs: " PUBLIC_LOG_D32, timeoutMs);
111         return false;
112     }
113     if (!condInited_) {
114         MEDIA_LOG_E("WaitFor uninitialized pthread cond");
115         return false;
116     }
117     struct timespec timeout = {0, 0};
118 #ifdef USING_CLOCK_REALTIME
119     clock_gettime(CLOCK_REALTIME, &timeout);
120 #else
121     clock_gettime(CLOCK_MONOTONIC, &timeout);
122 #endif
123     timeout = NsToTm(TmToNs(timeout) + timeoutMs * std::mega::num);
124     return pthread_cond_timedwait(&cond_, &(lock.mutex_->nativeHandle_), &timeout) == 0;
125 }
126 
WaitFor(AutoLock & lock,int timeoutMs,std::function<bool ()> pred)127 bool ConditionVariable::WaitFor(AutoLock& lock, int timeoutMs, std::function<bool()> pred)
128 {
129     if (timeoutMs < 0) {
130         MEDIA_LOG_E("ConditionVariable WaitUntil invalid timeoutMs: " PUBLIC_LOG_D32, timeoutMs);
131         return false;
132     }
133     if (!condInited_) {
134         MEDIA_LOG_E("WaitFor uninitialized pthread cond");
135         return false;
136     }
137     struct timespec timeout = {0, 0};
138 #ifdef USING_CLOCK_REALTIME
139     clock_gettime(CLOCK_REALTIME, &timeout);
140 #else
141     clock_gettime(CLOCK_MONOTONIC, &timeout);
142 #endif
143     timeout = NsToTm(TmToNs(timeout) + timeoutMs * std::mega::num);
144     int status = 0;
145     while (!pred() && (status == 0)) {
146         status = pthread_cond_timedwait(&cond_, &(lock.mutex_->nativeHandle_), &timeout);
147         if (status == ETIMEDOUT) {
148             return pred();
149         }
150     }
151     return status == 0;
152 }
153 } // namespace Media
154 } // namespace OHOS
155