1 /* 2 * Copyright (c) 2021-2022 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 #ifndef AUDIO_TIMER_H 17 #define AUDIO_TIMER_H 18 19 #include <atomic> 20 #include <condition_variable> 21 #include <mutex> 22 #include <thread> 23 #include <functional> 24 25 namespace OHOS { 26 namespace AudioStandard { 27 const uint32_t WAIT_TIMEOUT_IN_SECS = 5; 28 29 class AudioTimer { 30 public: AudioTimer()31 AudioTimer() 32 : AudioTimer(nullptr) 33 { 34 } 35 AudioTimer(std::function<void ()> func)36 AudioTimer(std::function<void()> func) 37 { 38 timeoutDuration = WAIT_TIMEOUT_IN_SECS; 39 isTimerStarted = false; 40 isTimedOut = false; 41 exitLoop = false; 42 timeOutCallBack_ = func; 43 timerLoop = std::thread([this] { this->TimerLoopFunc(); }); 44 pthread_setname_np(timerLoop.native_handle(), "OS_ATimer"); 45 } 46 ~AudioTimer()47 virtual ~AudioTimer() 48 { 49 { 50 std::unique_lock<std::mutex> lck(timerMutex); 51 exitLoop = true; 52 isTimerStarted = !isTimerStarted; 53 timerCtrl.notify_one(); 54 } 55 if (timerLoop.joinable()) { 56 timerLoop.join(); 57 } 58 } 59 StartTimer(uint32_t duration)60 void StartTimer(uint32_t duration) 61 { 62 std::unique_lock<std::mutex> lck(timerMutex); 63 timeoutDuration = duration; 64 isTimerStarted = true; 65 timerCtrl.notify_one(); 66 } 67 StopTimer()68 void StopTimer() 69 { 70 std::unique_lock<std::mutex> lck(timerMutex); 71 isTimerStarted = false; 72 if (!isTimedOut) { 73 timerCtrl.notify_one(); 74 } 75 } 76 IsTimeOut()77 bool IsTimeOut() 78 { 79 return isTimedOut; 80 } 81 OnTimeOut()82 virtual void OnTimeOut() {}; 83 84 volatile std::atomic<bool> isTimedOut; 85 86 private: 87 std::thread timerLoop; 88 std::condition_variable timerCtrl; 89 volatile std::atomic<bool> isTimerStarted; 90 std::mutex timerMutex; 91 volatile bool exitLoop; 92 uint32_t timeoutDuration; 93 std::function<void()> timeOutCallBack_ = nullptr; 94 TimerLoopFunc()95 void TimerLoopFunc() 96 { 97 while (true) { 98 bool isCallBack = false; 99 { 100 std::unique_lock<std::mutex> lck(timerMutex); 101 if (exitLoop) { 102 break; 103 } 104 if (isTimerStarted) { 105 if (!timerCtrl.wait_for(lck, std::chrono::seconds(timeoutDuration), 106 [this] { return CheckTimerStopped() || exitLoop; })) { 107 isTimedOut = true; 108 isCallBack = !exitLoop; 109 isTimerStarted = false; 110 OnTimeOut(); 111 } 112 } else { 113 timerCtrl.wait(lck, [this] { return CheckTimerStarted() || exitLoop; }); 114 isTimedOut = false; 115 } 116 } 117 if (isCallBack && timeOutCallBack_ != nullptr) { 118 timeOutCallBack_(); 119 } 120 } 121 } 122 CheckTimerStarted()123 bool CheckTimerStarted() 124 { 125 return this->isTimerStarted; 126 } 127 CheckTimerStopped()128 bool CheckTimerStopped() 129 { 130 return !this->isTimerStarted; 131 } 132 }; 133 } // namespace AudioStandard 134 } // namespace OHOS 135 #endif // AUDIO_TIMER_H 136