1 /* 2 * Copyright (c) 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 #ifndef SHAREDDATA_H 17 #define SHAREDDATA_H 18 19 #include <functional> 20 #include <list> 21 #include <map> 22 #include <mutex> 23 #include <thread> 24 25 #include "SharedDataManager.h" 26 #include "PreviewerEngineLog.h" 27 28 template<typename T> class SharedData { 29 public: SharedData()30 SharedData() : value(), isChanged(false), minValue(), maxValue() {} 31 ~SharedData()32 ~SharedData() {} 33 value(v)34 SharedData(SharedDataType type, T v, T min = T(), T max = T()) : value(v), minValue(min), maxValue(max) 35 { 36 staticDataMutex.lock(); 37 isChanged = false; 38 dataMap[type] = *this; 39 staticDataMutex.unlock(); 40 41 SharedDataManager::AddChecker(SharedData<T>::CheckAll); 42 } 43 SetData(SharedDataType type,T v)44 static bool SetData(SharedDataType type, T v) 45 { 46 staticDataMutex.lock(); 47 if (dataMap.find(type) == dataMap.end()) { 48 FLOG("SharedData::SetData invalid data type."); 49 return false; 50 } 51 52 SharedData data = dataMap[type]; 53 if ((data.minValue != data.maxValue) && (v < data.minValue || v > data.maxValue)) { 54 staticDataMutex.unlock(); 55 return false; 56 } 57 data.value = v; 58 data.isChanged = true; 59 dataMap[type] = data; 60 staticDataMutex.unlock(); 61 return true; 62 } 63 GetData(SharedDataType type)64 static T GetData(SharedDataType type) 65 { 66 const std::lock_guard<std::mutex> lock(staticDataMutex); 67 if (dataMap.find(type) == dataMap.end()) { 68 FLOG("SharedData::GetData invalid data type."); 69 } 70 71 return dataMap[type].value; 72 } 73 IsValid(SharedDataType type,T v)74 static bool IsValid(SharedDataType type, T v) 75 { 76 const std::lock_guard<std::mutex> lock(staticDataMutex); 77 if (dataMap.find(type) == dataMap.end()) { 78 FLOG("SharedData::IsValid invalid data type."); 79 } 80 81 if ((dataMap[type].minValue != dataMap[type].maxValue) && 82 (v < dataMap[type].minValue || v > dataMap[type].maxValue)) { 83 ILOG("%d %d %d", v, dataMap[type].minValue, dataMap[type].maxValue); 84 return false; 85 } 86 87 return true; 88 } 89 90 /* 91 * Checks whether the current data is changed. 92 * Return a list of data changed callback 93 */ Check()94 std::list<std::pair<std::function<void(T)>, T>> Check() 95 { 96 std::thread::id curThreadId = std::this_thread::get_id(); 97 if (ticksMap.find(curThreadId) == ticksMap.end()) { 98 ticksMap[curThreadId] = 0; 99 } 100 uint32_t ticks = ticksMap[curThreadId] + 1; 101 ticksMap[curThreadId] = ticks; 102 103 std::list<std::pair<std::function<void(T)>, T>> pairs; 104 if (!isChanged) { 105 return pairs; 106 } 107 for (auto iter = callBacks.begin(); iter != callBacks.end(); ++iter) { 108 if (iter->first == curThreadId && ticks % iter->second.second == 0) { 109 isChanged = false; 110 pairs.push_back(std::make_pair(iter->second.first, value)); 111 } 112 } 113 114 return pairs; 115 } 116 117 /* 118 * Add a data changed callback 119 * type: Checked data type 120 * func: Callback 121 * threadId: Checks and callbacks are performed only in this thread. 122 * period: Indicates the detection period. The unit is 100 ms. 123 */ 124 static void 125 AppendNotify(SharedDataType type, std::function<void(T)> func, std::thread::id threadId, uint32_t period = 1) 126 { 127 staticDataMutex.lock(); 128 if (dataMap.find(type) == dataMap.end()) { 129 FLOG("SharedData::IsValid invalid data type."); 130 } 131 dataMap[type].callBacks[threadId] = std::pair<std::function<void(T)>, uint32_t>(func, period); 132 staticDataMutex.unlock(); 133 } 134 135 // Check whether the data is changes and execute the notification callback. CheckAll()136 static void CheckAll() 137 { 138 std::list<std::pair<std::function<void(T)>, T>> pairs; 139 staticDataMutex.lock(); 140 for (auto dataIter = dataMap.begin(); dataIter != dataMap.end(); ++dataIter) { 141 auto checkers = dataIter->second.Check(); 142 pairs.insert(pairs.end(), checkers.begin(), checkers.end()); 143 } 144 staticDataMutex.unlock(); 145 146 for (auto pair : pairs) { 147 pair.first(pair.second); 148 } 149 } 150 151 private: 152 T value; 153 bool isChanged; 154 T minValue; 155 T maxValue; 156 // map<thread id, pair<callback, detection period>> 157 std::map<std::thread::id, std::pair<std::function<void(T)>, uint32_t>> callBacks; 158 // map<thread id, current time tick> 159 std::map<std::thread::id, uint32_t> ticksMap; 160 static std::map<SharedDataType, SharedData> dataMap; 161 static std::mutex staticDataMutex; 162 }; 163 164 template<typename T> std::map<SharedDataType, SharedData<T>> SharedData<T>::dataMap; 165 166 template<typename T> std::mutex SharedData<T>::staticDataMutex; 167 168 #endif // SHAREDDATA_H 169