xref: /ide/tools/previewer/util/SharedData.h (revision 7c804472)
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
28template<typename T> class SharedData {
29public:
30    SharedData() : value(), isChanged(false), minValue(), maxValue() {}
31
32    ~SharedData() {}
33
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
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
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
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     */
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.
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
152private:
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
165template<typename T> std::map<SharedDataType, SharedData<T>> SharedData<T>::dataMap;
166
167template<typename T> std::mutex SharedData<T>::staticDataMutex;
168
169#endif // SHAREDDATA_H
170