1 /* 2 * Copyright (c) 2021-2021 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 HISTREAMER_FOUNDATION_OSAL_BASE_SYNCHRONIZER_H 17 #define HISTREAMER_FOUNDATION_OSAL_BASE_SYNCHRONIZER_H 18 19 #include <functional> 20 #include <map> 21 #include <set> 22 #include <string> 23 24 #include "foundation/log.h" 25 #include "thread/condition_variable.h" 26 #include "thread/mutex.h" 27 28 namespace OHOS { 29 namespace Media { 30 namespace OSAL { 31 template <typename SyncIdType, typename ResultType = void> 32 class Synchronizer { 33 public: Synchronizer(std::string name)34 explicit Synchronizer(std::string name) : name_(std::move(name)) 35 { 36 } 37 38 Synchronizer(const Synchronizer<SyncIdType, ResultType>&) = delete; 39 40 Synchronizer<SyncIdType, ResultType>& operator=(const Synchronizer<SyncIdType, ResultType>&) = delete; 41 42 virtual ~Synchronizer() = default; 43 Wait(SyncIdType syncId,const std::function<void ()> & asyncOps)44 void Wait(SyncIdType syncId, const std::function<void()>& asyncOps) 45 { 46 MEDIA_LOG_I("Synchronizer %" PUBLIC_LOG "s Wait for %" PUBLIC_LOG "d", 47 name_.c_str(), static_cast<int>(syncId)); 48 if (asyncOps) { 49 OSAL::ScopedLock lock(mutex_); 50 waitSet_.insert(syncId); 51 asyncOps(); 52 cv_.Wait(lock, [this, syncId] { return syncMap_.find(syncId) != syncMap_.end(); }); 53 syncMap_.erase(syncId); 54 } 55 } 56 WaitFor(SyncIdType syncId,const std::function<void ()> & asyncOps,int timeoutMs)57 bool WaitFor(SyncIdType syncId, const std::function<void()>& asyncOps, int timeoutMs) 58 { 59 MEDIA_LOG_I("Synchronizer %" PUBLIC_LOG "s Wait for %" PUBLIC_LOG "d, timeout: %" PUBLIC_LOG "d", 60 name_.c_str(), static_cast<int>(syncId), timeoutMs); 61 if (!asyncOps) { 62 return false; 63 } 64 OSAL::ScopedLock lock(mutex_); 65 waitSet_.insert(syncId); 66 asyncOps(); 67 auto rtv = cv_.WaitFor(lock, timeoutMs, [this, syncId] { return syncMap_.find(syncId) != syncMap_.end(); }); 68 if (rtv) { 69 syncMap_.erase(syncId); 70 } else { 71 waitSet_.erase(syncId); 72 } 73 return rtv; 74 } 75 Wait(SyncIdType syncId,const std::function<void ()> & asyncOps,ResultType & result)76 void Wait(SyncIdType syncId, const std::function<void()>& asyncOps, ResultType& result) 77 { 78 MEDIA_LOG_I("Synchronizer %" PUBLIC_LOG "s Wait for %" PUBLIC_LOG "d", 79 name_.c_str(), static_cast<int>(syncId)); 80 if (asyncOps) { 81 OSAL::ScopedLock lock(mutex_); 82 waitSet_.insert(syncId); 83 asyncOps(); 84 cv_.Wait(lock, [this, syncId] { return syncMap_.find(syncId) != syncMap_.end(); }); 85 result = syncMap_[syncId]; 86 syncMap_.erase(syncId); 87 } 88 } 89 WaitFor(SyncIdType syncId,const std::function<void ()> & asyncOps,int timeoutMs,ResultType & result)90 bool WaitFor(SyncIdType syncId, const std::function<void()>& asyncOps, int timeoutMs, ResultType& result) 91 { 92 MEDIA_LOG_I("Synchronizer %" PUBLIC_LOG "s Wait for %" PUBLIC_LOG "d, timeout: %" PUBLIC_LOG "d", 93 name_.c_str(), static_cast<int>(syncId), timeoutMs); 94 if (!asyncOps) { 95 return false; 96 } 97 OSAL::ScopedLock lock(mutex_); 98 waitSet_.insert(syncId); 99 asyncOps(); 100 auto rtv = cv_.WaitFor(lock, timeoutMs, [this, syncId] { return syncMap_.find(syncId) != syncMap_.end(); }); 101 if (rtv) { 102 result = syncMap_[syncId]; 103 syncMap_.erase(syncId); 104 MEDIA_LOG_D("Synchronizer %" PUBLIC_LOG "s return.", name_.c_str()); 105 } else { 106 waitSet_.erase(syncId); 107 } 108 return rtv; 109 } 110 111 void Notify(SyncIdType syncId, ResultType result = ResultType()) 112 { 113 MEDIA_LOG_I("Synchronizer %" PUBLIC_LOG "s Notify: %" PUBLIC_LOG "d", 114 name_.c_str(), static_cast<int>(syncId)); 115 OSAL::ScopedLock lock(mutex_); 116 if (waitSet_.find(syncId) != waitSet_.end()) { 117 waitSet_.erase(syncId); 118 syncMap_.insert({syncId, result}); 119 cv_.NotifyAll(); 120 } 121 } 122 123 private: 124 Mutex mutex_; 125 ConditionVariable cv_; 126 std::string name_; 127 std::map<SyncIdType, ResultType> syncMap_; 128 std::set<SyncIdType> waitSet_; 129 }; 130 } // namespace OSAL 131 } // namespace Media 132 } // namespace OHOS 133 #endif // HISTREAMER_FOUNDATION_OSAL_BASE_SYNCHRONIZER_H 134