/* * Copyright (c) 2021-2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef HISTREAMER_FOUNDATION_OSAL_BASE_SYNCHRONIZER_H #define HISTREAMER_FOUNDATION_OSAL_BASE_SYNCHRONIZER_H #include #include #include #include #include "inner_api/common/log.h" #include "inner_api/osal/task/condition_variable.h" #include "inner_api/osal/task/mutex.h" namespace OHOS { namespace Media { template class Synchronizer { public: explicit Synchronizer(std::string name) : name_(std::move(name)) { } Synchronizer(const Synchronizer&) = delete; Synchronizer& operator=(const Synchronizer&) = delete; virtual ~Synchronizer() = default; void Wait(SyncIdType syncId, const std::function& asyncOps) { MEDIA_LOG_I("Synchronizer " PUBLIC_LOG_S " Wait for " PUBLIC_LOG_D32, name_.c_str(), static_cast(syncId)); if (asyncOps) { OSAL::ScopedLock lock(mutex_); waitSet_.insert(syncId); asyncOps(); cv_.Wait(lock, [this, syncId] { return syncMap_.find(syncId) != syncMap_.end(); }); syncMap_.erase(syncId); } } bool WaitFor(SyncIdType syncId, const std::function& asyncOps, int timeoutMs) { MEDIA_LOG_I("Synchronizer " PUBLIC_LOG_S " Wait for " PUBLIC_LOG_D32 ", timeout: " PUBLIC_LOG_D32, name_.c_str(), static_cast(syncId), timeoutMs); if (!asyncOps) { return false; } OSAL::ScopedLock lock(mutex_); waitSet_.insert(syncId); asyncOps(); auto rtv = cv_.WaitFor(lock, timeoutMs, [this, syncId] { return syncMap_.find(syncId) != syncMap_.end(); }); if (rtv) { syncMap_.erase(syncId); } else { waitSet_.erase(syncId); } return rtv; } void Wait(SyncIdType syncId, const std::function& asyncOps, ResultType& result) { MEDIA_LOG_I("Synchronizer " PUBLIC_LOG_S " Wait for " PUBLIC_LOG_D32, name_.c_str(), static_cast(syncId)); if (asyncOps) { OSAL::ScopedLock lock(mutex_); waitSet_.insert(syncId); asyncOps(); cv_.Wait(lock, [this, syncId] { return syncMap_.find(syncId) != syncMap_.end(); }); result = syncMap_[syncId]; syncMap_.erase(syncId); } } bool WaitFor(SyncIdType syncId, const std::function& asyncOps, int timeoutMs, ResultType& result) { MEDIA_LOG_I("Synchronizer " PUBLIC_LOG_S " Wait for " PUBLIC_LOG_D32 ", timeout: " PUBLIC_LOG_D32, name_.c_str(), static_cast(syncId), timeoutMs); if (!asyncOps) { return false; } OSAL::ScopedLock lock(mutex_); waitSet_.insert(syncId); if (!asyncOps()) { waitSet_.erase(syncId); return false; } auto rtv = cv_.WaitFor(lock, timeoutMs, [this, syncId] { return syncMap_.find(syncId) != syncMap_.end(); }); if (rtv) { result = syncMap_[syncId]; syncMap_.erase(syncId); MEDIA_LOG_D("Synchronizer " PUBLIC_LOG_S " Wait for " PUBLIC_LOG_D32 " return.", name_.c_str(), static_cast(syncId)); } else { waitSet_.erase(syncId); } return rtv; } void Notify(SyncIdType syncId, ResultType result = ResultType()) { MEDIA_LOG_I("Synchronizer " PUBLIC_LOG_S " Notify: " PUBLIC_LOG_D32, name_.c_str(), static_cast(syncId)); OSAL::ScopedLock lock(mutex_); if (waitSet_.find(syncId) != waitSet_.end()) { waitSet_.erase(syncId); syncMap_.insert({syncId, result}); cv_.NotifyAll(); } } private: static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_FOUNDATION, "Synchronizer" }; Mutex mutex_; ConditionVariable cv_; std::string name_; std::map syncMap_; std::set waitSet_; }; } // namespace Media } // namespace OHOS #endif // HISTREAMER_FOUNDATION_OSAL_BASE_SYNCHRONIZER_H