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 23namespace { 24constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_FOUNDATION, "ConditionVariable" }; 25} 26 27namespace { 28inline long long TmToNs(struct timespec tm) 29{ 30 return tm.tv_sec * std::giga::num + tm.tv_nsec; 31} 32 33inline struct timespec NsToTm(long long ns) 34{ 35 return {ns / std::giga::num, static_cast<long>(ns % std::giga::num)}; 36} 37} 38 39namespace OHOS { 40namespace Media { 41ConditionVariable::ConditionVariable() noexcept : condInited_(true) 42{ 43 pthread_condattr_t attr; 44 pthread_condattr_init(&attr); 45#ifndef __LITEOS_M__ 46#ifdef USING_CLOCK_REALTIME 47 pthread_condattr_setclock(&attr, CLOCK_REALTIME); 48#else 49 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); 50#endif 51#endif 52 int rtv = pthread_cond_init(&cond_, &attr); 53 if (rtv != 0) { 54 condInited_ = false; 55 MEDIA_LOG_E("failed to init pthread cond variable"); 56 } 57 pthread_condattr_destroy(&attr); 58} 59 60ConditionVariable::~ConditionVariable() noexcept 61{ 62 if (condInited_) { 63 pthread_cond_destroy(&cond_); 64 } 65} 66 67void ConditionVariable::NotifyOne() noexcept 68{ 69 FALSE_RETURN_MSG(condInited_, "NotifyOne uninitialized pthread cond"); 70 int ret = pthread_cond_signal(&cond_); 71 FALSE_LOG_MSG(ret == 0, "NotifyOne failed with errno = " PUBLIC_LOG_D32, ret); 72} 73 74void ConditionVariable::NotifyAll() noexcept 75{ 76 FALSE_RETURN_MSG(condInited_, "NotifyAll uninitialized pthread cond"); 77 int ret = pthread_cond_broadcast(&cond_); 78 FALSE_LOG_MSG(ret == 0, "NotifyAll failed with errno = " PUBLIC_LOG_D32, ret); 79} 80 81void ConditionVariable::Wait(AutoLock& lock) noexcept 82{ 83 FALSE_RETURN_MSG(condInited_, "Wait uninitialized pthread cond"); 84 pthread_cond_wait(&cond_, &(lock.mutex_->nativeHandle_)); 85} 86 87void ConditionVariable::Wait(AutoLock& lock, std::function<bool()> pred) noexcept 88{ 89 FALSE_RETURN_MSG(condInited_, "Wait uninitialized pthread cond"); 90 while (!pred()) { 91 Wait(lock); 92 } 93} 94 95bool ConditionVariable::WaitFor(AutoLock& lock, int64_t timeoutMs) 96{ 97 FALSE_RETURN_V_MSG_E(timeoutMs >= 0, 98 false, "ConditionVariable WaitUntil invalid timeoutMs: " PUBLIC_LOG_D64, timeoutMs); 99 FALSE_RETURN_V_MSG_E(condInited_, 100 false, "WaitFor uninitialized pthread cond"); 101 struct timespec timeout = {0, 0}; 102#ifdef USING_CLOCK_REALTIME 103 clock_gettime(CLOCK_REALTIME, &timeout); 104#else 105 clock_gettime(CLOCK_MONOTONIC, &timeout); 106#endif 107 timeout = NsToTm(TmToNs(timeout) + timeoutMs * std::mega::num); 108 return pthread_cond_timedwait(&cond_, &(lock.mutex_->nativeHandle_), &timeout) == 0; 109} 110 111bool ConditionVariable::WaitFor(AutoLock& lock, int64_t timeoutMs, std::function<bool()> pred) 112{ 113 FALSE_RETURN_V_MSG_E(timeoutMs >= 0, 114 false, "ConditionVariable WaitUntil invalid timeoutMs: " PUBLIC_LOG_D64, timeoutMs); 115 FALSE_RETURN_V_MSG_E(condInited_, 116 false, "WaitFor uninitialized pthread cond"); 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 int status = 0; 125 while (!pred() && (status == 0)) { 126 status = pthread_cond_timedwait(&cond_, &(lock.mutex_->nativeHandle_), &timeout); 127 if (status == ETIMEDOUT) { 128 return pred(); 129 } 130 } 131 return status == 0; 132} 133} // namespace Media 134} // namespace OHOS 135