1fa7767c5Sopenharmony_ci/* 2fa7767c5Sopenharmony_ci * Copyright (c) 2021-2021 Huawei Device Co., Ltd. 3fa7767c5Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fa7767c5Sopenharmony_ci * you may not use this file except in compliance with the License. 5fa7767c5Sopenharmony_ci * You may obtain a copy of the License at 6fa7767c5Sopenharmony_ci * 7fa7767c5Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fa7767c5Sopenharmony_ci * 9fa7767c5Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fa7767c5Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fa7767c5Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fa7767c5Sopenharmony_ci * See the License for the specific language governing permissions and 13fa7767c5Sopenharmony_ci * limitations under the License. 14fa7767c5Sopenharmony_ci */ 15fa7767c5Sopenharmony_ci 16fa7767c5Sopenharmony_ci#ifndef HISTREAMER_FOUNDATION_OSAL_BASE_SYNCHRONIZER_H 17fa7767c5Sopenharmony_ci#define HISTREAMER_FOUNDATION_OSAL_BASE_SYNCHRONIZER_H 18fa7767c5Sopenharmony_ci 19fa7767c5Sopenharmony_ci#include <functional> 20fa7767c5Sopenharmony_ci#include <map> 21fa7767c5Sopenharmony_ci#include <set> 22fa7767c5Sopenharmony_ci#include <string> 23fa7767c5Sopenharmony_ci 24fa7767c5Sopenharmony_ci#include "inner_api/common/log.h" 25fa7767c5Sopenharmony_ci#include "inner_api/osal/task/condition_variable.h" 26fa7767c5Sopenharmony_ci#include "inner_api/osal/task/mutex.h" 27fa7767c5Sopenharmony_ci 28fa7767c5Sopenharmony_cinamespace OHOS { 29fa7767c5Sopenharmony_cinamespace Media { 30fa7767c5Sopenharmony_citemplate <typename SyncIdType, typename ResultType = void> 31fa7767c5Sopenharmony_ciclass Synchronizer { 32fa7767c5Sopenharmony_cipublic: 33fa7767c5Sopenharmony_ci explicit Synchronizer(std::string name) : name_(std::move(name)) 34fa7767c5Sopenharmony_ci { 35fa7767c5Sopenharmony_ci } 36fa7767c5Sopenharmony_ci 37fa7767c5Sopenharmony_ci Synchronizer(const Synchronizer<SyncIdType, ResultType>&) = delete; 38fa7767c5Sopenharmony_ci 39fa7767c5Sopenharmony_ci Synchronizer<SyncIdType, ResultType>& operator=(const Synchronizer<SyncIdType, ResultType>&) = delete; 40fa7767c5Sopenharmony_ci 41fa7767c5Sopenharmony_ci virtual ~Synchronizer() = default; 42fa7767c5Sopenharmony_ci 43fa7767c5Sopenharmony_ci void Wait(SyncIdType syncId, const std::function<void()>& asyncOps) 44fa7767c5Sopenharmony_ci { 45fa7767c5Sopenharmony_ci MEDIA_LOG_I("Synchronizer " PUBLIC_LOG_S " Wait for " PUBLIC_LOG_D32, 46fa7767c5Sopenharmony_ci name_.c_str(), static_cast<int>(syncId)); 47fa7767c5Sopenharmony_ci if (asyncOps) { 48fa7767c5Sopenharmony_ci OSAL::ScopedLock lock(mutex_); 49fa7767c5Sopenharmony_ci waitSet_.insert(syncId); 50fa7767c5Sopenharmony_ci asyncOps(); 51fa7767c5Sopenharmony_ci cv_.Wait(lock, [this, syncId] { return syncMap_.find(syncId) != syncMap_.end(); }); 52fa7767c5Sopenharmony_ci syncMap_.erase(syncId); 53fa7767c5Sopenharmony_ci } 54fa7767c5Sopenharmony_ci } 55fa7767c5Sopenharmony_ci 56fa7767c5Sopenharmony_ci bool WaitFor(SyncIdType syncId, const std::function<void()>& asyncOps, int timeoutMs) 57fa7767c5Sopenharmony_ci { 58fa7767c5Sopenharmony_ci MEDIA_LOG_I("Synchronizer " PUBLIC_LOG_S " Wait for " PUBLIC_LOG_D32 ", timeout: " PUBLIC_LOG_D32, 59fa7767c5Sopenharmony_ci name_.c_str(), static_cast<int>(syncId), timeoutMs); 60fa7767c5Sopenharmony_ci if (!asyncOps) { 61fa7767c5Sopenharmony_ci return false; 62fa7767c5Sopenharmony_ci } 63fa7767c5Sopenharmony_ci OSAL::ScopedLock lock(mutex_); 64fa7767c5Sopenharmony_ci waitSet_.insert(syncId); 65fa7767c5Sopenharmony_ci asyncOps(); 66fa7767c5Sopenharmony_ci auto rtv = cv_.WaitFor(lock, timeoutMs, [this, syncId] { return syncMap_.find(syncId) != syncMap_.end(); }); 67fa7767c5Sopenharmony_ci if (rtv) { 68fa7767c5Sopenharmony_ci syncMap_.erase(syncId); 69fa7767c5Sopenharmony_ci } else { 70fa7767c5Sopenharmony_ci waitSet_.erase(syncId); 71fa7767c5Sopenharmony_ci } 72fa7767c5Sopenharmony_ci return rtv; 73fa7767c5Sopenharmony_ci } 74fa7767c5Sopenharmony_ci 75fa7767c5Sopenharmony_ci void Wait(SyncIdType syncId, const std::function<void()>& asyncOps, ResultType& result) 76fa7767c5Sopenharmony_ci { 77fa7767c5Sopenharmony_ci MEDIA_LOG_I("Synchronizer " PUBLIC_LOG_S " Wait for " PUBLIC_LOG_D32, 78fa7767c5Sopenharmony_ci name_.c_str(), static_cast<int>(syncId)); 79fa7767c5Sopenharmony_ci if (asyncOps) { 80fa7767c5Sopenharmony_ci OSAL::ScopedLock lock(mutex_); 81fa7767c5Sopenharmony_ci waitSet_.insert(syncId); 82fa7767c5Sopenharmony_ci asyncOps(); 83fa7767c5Sopenharmony_ci cv_.Wait(lock, [this, syncId] { return syncMap_.find(syncId) != syncMap_.end(); }); 84fa7767c5Sopenharmony_ci result = syncMap_[syncId]; 85fa7767c5Sopenharmony_ci syncMap_.erase(syncId); 86fa7767c5Sopenharmony_ci } 87fa7767c5Sopenharmony_ci } 88fa7767c5Sopenharmony_ci 89fa7767c5Sopenharmony_ci bool WaitFor(SyncIdType syncId, const std::function<bool()>& asyncOps, int timeoutMs, ResultType& result) 90fa7767c5Sopenharmony_ci { 91fa7767c5Sopenharmony_ci MEDIA_LOG_I("Synchronizer " PUBLIC_LOG_S " Wait for " PUBLIC_LOG_D32 ", timeout: " PUBLIC_LOG_D32, 92fa7767c5Sopenharmony_ci name_.c_str(), static_cast<int>(syncId), timeoutMs); 93fa7767c5Sopenharmony_ci if (!asyncOps) { 94fa7767c5Sopenharmony_ci return false; 95fa7767c5Sopenharmony_ci } 96fa7767c5Sopenharmony_ci OSAL::ScopedLock lock(mutex_); 97fa7767c5Sopenharmony_ci waitSet_.insert(syncId); 98fa7767c5Sopenharmony_ci if (!asyncOps()) { 99fa7767c5Sopenharmony_ci waitSet_.erase(syncId); 100fa7767c5Sopenharmony_ci return false; 101fa7767c5Sopenharmony_ci } 102fa7767c5Sopenharmony_ci auto rtv = cv_.WaitFor(lock, timeoutMs, [this, syncId] { return syncMap_.find(syncId) != syncMap_.end(); }); 103fa7767c5Sopenharmony_ci if (rtv) { 104fa7767c5Sopenharmony_ci result = syncMap_[syncId]; 105fa7767c5Sopenharmony_ci syncMap_.erase(syncId); 106fa7767c5Sopenharmony_ci MEDIA_LOG_D("Synchronizer " PUBLIC_LOG_S " Wait for " PUBLIC_LOG_D32 " return.", name_.c_str(), 107fa7767c5Sopenharmony_ci static_cast<int>(syncId)); 108fa7767c5Sopenharmony_ci } else { 109fa7767c5Sopenharmony_ci waitSet_.erase(syncId); 110fa7767c5Sopenharmony_ci } 111fa7767c5Sopenharmony_ci return rtv; 112fa7767c5Sopenharmony_ci } 113fa7767c5Sopenharmony_ci 114fa7767c5Sopenharmony_ci void Notify(SyncIdType syncId, ResultType result = ResultType()) 115fa7767c5Sopenharmony_ci { 116fa7767c5Sopenharmony_ci MEDIA_LOG_I("Synchronizer " PUBLIC_LOG_S " Notify: " PUBLIC_LOG_D32, 117fa7767c5Sopenharmony_ci name_.c_str(), static_cast<int>(syncId)); 118fa7767c5Sopenharmony_ci OSAL::ScopedLock lock(mutex_); 119fa7767c5Sopenharmony_ci if (waitSet_.find(syncId) != waitSet_.end()) { 120fa7767c5Sopenharmony_ci waitSet_.erase(syncId); 121fa7767c5Sopenharmony_ci syncMap_.insert({syncId, result}); 122fa7767c5Sopenharmony_ci cv_.NotifyAll(); 123fa7767c5Sopenharmony_ci } 124fa7767c5Sopenharmony_ci } 125fa7767c5Sopenharmony_ci 126fa7767c5Sopenharmony_ciprivate: 127fa7767c5Sopenharmony_ci static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_FOUNDATION, "Synchronizer" }; 128fa7767c5Sopenharmony_ci Mutex mutex_; 129fa7767c5Sopenharmony_ci ConditionVariable cv_; 130fa7767c5Sopenharmony_ci std::string name_; 131fa7767c5Sopenharmony_ci std::map<SyncIdType, ResultType> syncMap_; 132fa7767c5Sopenharmony_ci std::set<SyncIdType> waitSet_; 133fa7767c5Sopenharmony_ci}; 134fa7767c5Sopenharmony_ci} // namespace Media 135fa7767c5Sopenharmony_ci} // namespace OHOS 136fa7767c5Sopenharmony_ci#endif // HISTREAMER_FOUNDATION_OSAL_BASE_SYNCHRONIZER_H 137