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