17c804472Sopenharmony_ci/*
27c804472Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
37c804472Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
47c804472Sopenharmony_ci * you may not use this file except in compliance with the License.
57c804472Sopenharmony_ci * You may obtain a copy of the License at
67c804472Sopenharmony_ci *
77c804472Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
87c804472Sopenharmony_ci *
97c804472Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
107c804472Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
117c804472Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127c804472Sopenharmony_ci * See the License for the specific language governing permissions and
137c804472Sopenharmony_ci * limitations under the License.
147c804472Sopenharmony_ci */
157c804472Sopenharmony_ci
167c804472Sopenharmony_ci#ifndef SHAREDDATA_H
177c804472Sopenharmony_ci#define SHAREDDATA_H
187c804472Sopenharmony_ci
197c804472Sopenharmony_ci#include <functional>
207c804472Sopenharmony_ci#include <list>
217c804472Sopenharmony_ci#include <map>
227c804472Sopenharmony_ci#include <mutex>
237c804472Sopenharmony_ci#include <thread>
247c804472Sopenharmony_ci
257c804472Sopenharmony_ci#include "SharedDataManager.h"
267c804472Sopenharmony_ci#include "PreviewerEngineLog.h"
277c804472Sopenharmony_ci
287c804472Sopenharmony_citemplate<typename T> class SharedData {
297c804472Sopenharmony_cipublic:
307c804472Sopenharmony_ci    SharedData() : value(), isChanged(false), minValue(), maxValue() {}
317c804472Sopenharmony_ci
327c804472Sopenharmony_ci    ~SharedData() {}
337c804472Sopenharmony_ci
347c804472Sopenharmony_ci    SharedData(SharedDataType type, T v, T min = T(), T max = T()) : value(v), minValue(min), maxValue(max)
357c804472Sopenharmony_ci    {
367c804472Sopenharmony_ci        staticDataMutex.lock();
377c804472Sopenharmony_ci        isChanged = false;
387c804472Sopenharmony_ci        dataMap[type] = *this;
397c804472Sopenharmony_ci        staticDataMutex.unlock();
407c804472Sopenharmony_ci
417c804472Sopenharmony_ci        SharedDataManager::AddChecker(SharedData<T>::CheckAll);
427c804472Sopenharmony_ci    }
437c804472Sopenharmony_ci
447c804472Sopenharmony_ci    static bool SetData(SharedDataType type, T v)
457c804472Sopenharmony_ci    {
467c804472Sopenharmony_ci        staticDataMutex.lock();
477c804472Sopenharmony_ci        if (dataMap.find(type) == dataMap.end()) {
487c804472Sopenharmony_ci            staticDataMutex.unlock();
497c804472Sopenharmony_ci            FLOG("SharedData::SetData invalid data type.");
507c804472Sopenharmony_ci            return false;
517c804472Sopenharmony_ci        }
527c804472Sopenharmony_ci
537c804472Sopenharmony_ci        SharedData data = dataMap[type];
547c804472Sopenharmony_ci        if ((data.minValue != data.maxValue) && (v < data.minValue || v > data.maxValue)) {
557c804472Sopenharmony_ci            staticDataMutex.unlock();
567c804472Sopenharmony_ci            return false;
577c804472Sopenharmony_ci        }
587c804472Sopenharmony_ci        data.value = v;
597c804472Sopenharmony_ci        data.isChanged = true;
607c804472Sopenharmony_ci        dataMap[type] = data;
617c804472Sopenharmony_ci        staticDataMutex.unlock();
627c804472Sopenharmony_ci        return true;
637c804472Sopenharmony_ci    }
647c804472Sopenharmony_ci
657c804472Sopenharmony_ci    static T GetData(SharedDataType type)
667c804472Sopenharmony_ci    {
677c804472Sopenharmony_ci        const std::lock_guard<std::mutex> lock(staticDataMutex);
687c804472Sopenharmony_ci        if (dataMap.find(type) == dataMap.end()) {
697c804472Sopenharmony_ci            FLOG("SharedData::GetData invalid data type.");
707c804472Sopenharmony_ci        }
717c804472Sopenharmony_ci
727c804472Sopenharmony_ci        return dataMap[type].value;
737c804472Sopenharmony_ci    }
747c804472Sopenharmony_ci
757c804472Sopenharmony_ci    static bool IsValid(SharedDataType type, T v)
767c804472Sopenharmony_ci    {
777c804472Sopenharmony_ci        const std::lock_guard<std::mutex> lock(staticDataMutex);
787c804472Sopenharmony_ci        if (dataMap.find(type) == dataMap.end()) {
797c804472Sopenharmony_ci            FLOG("SharedData::IsValid invalid data type.");
807c804472Sopenharmony_ci        }
817c804472Sopenharmony_ci
827c804472Sopenharmony_ci        if ((dataMap[type].minValue != dataMap[type].maxValue) &&
837c804472Sopenharmony_ci            (v < dataMap[type].minValue || v > dataMap[type].maxValue)) {
847c804472Sopenharmony_ci            ILOG("%d %d %d", v, dataMap[type].minValue, dataMap[type].maxValue);
857c804472Sopenharmony_ci            return false;
867c804472Sopenharmony_ci        }
877c804472Sopenharmony_ci
887c804472Sopenharmony_ci        return true;
897c804472Sopenharmony_ci    }
907c804472Sopenharmony_ci
917c804472Sopenharmony_ci    /*
927c804472Sopenharmony_ci     * Checks whether the current data is changed.
937c804472Sopenharmony_ci     * Return a list of data changed callback
947c804472Sopenharmony_ci     */
957c804472Sopenharmony_ci    std::list<std::pair<std::function<void(T)>, T>> Check()
967c804472Sopenharmony_ci    {
977c804472Sopenharmony_ci        std::thread::id curThreadId = std::this_thread::get_id();
987c804472Sopenharmony_ci        if (ticksMap.find(curThreadId) == ticksMap.end()) {
997c804472Sopenharmony_ci            ticksMap[curThreadId] = 0;
1007c804472Sopenharmony_ci        }
1017c804472Sopenharmony_ci        uint32_t ticks = ticksMap[curThreadId] + 1;
1027c804472Sopenharmony_ci        ticksMap[curThreadId] = ticks;
1037c804472Sopenharmony_ci
1047c804472Sopenharmony_ci        std::list<std::pair<std::function<void(T)>, T>> pairs;
1057c804472Sopenharmony_ci        if (!isChanged) {
1067c804472Sopenharmony_ci            return pairs;
1077c804472Sopenharmony_ci        }
1087c804472Sopenharmony_ci        for (auto iter = callBacks.begin(); iter != callBacks.end(); ++iter) {
1097c804472Sopenharmony_ci            if (iter->first == curThreadId && ticks % iter->second.second == 0) {
1107c804472Sopenharmony_ci                isChanged = false;
1117c804472Sopenharmony_ci                pairs.push_back(std::make_pair(iter->second.first, value));
1127c804472Sopenharmony_ci            }
1137c804472Sopenharmony_ci        }
1147c804472Sopenharmony_ci
1157c804472Sopenharmony_ci        return pairs;
1167c804472Sopenharmony_ci    }
1177c804472Sopenharmony_ci
1187c804472Sopenharmony_ci    /*
1197c804472Sopenharmony_ci     * Add a data changed callback
1207c804472Sopenharmony_ci     * type: Checked data type
1217c804472Sopenharmony_ci     * func: Callback
1227c804472Sopenharmony_ci     * threadId: Checks and callbacks are performed only in this thread.
1237c804472Sopenharmony_ci     * period: Indicates the detection period. The unit is 100 ms.
1247c804472Sopenharmony_ci     */
1257c804472Sopenharmony_ci    static void
1267c804472Sopenharmony_ci        AppendNotify(SharedDataType type, std::function<void(T)> func, std::thread::id threadId, uint32_t period = 1)
1277c804472Sopenharmony_ci    {
1287c804472Sopenharmony_ci        staticDataMutex.lock();
1297c804472Sopenharmony_ci        if (dataMap.find(type) == dataMap.end()) {
1307c804472Sopenharmony_ci            FLOG("SharedData::IsValid invalid data type.");
1317c804472Sopenharmony_ci        }
1327c804472Sopenharmony_ci        dataMap[type].callBacks[threadId] = std::pair<std::function<void(T)>, uint32_t>(func, period);
1337c804472Sopenharmony_ci        staticDataMutex.unlock();
1347c804472Sopenharmony_ci    }
1357c804472Sopenharmony_ci
1367c804472Sopenharmony_ci    // Check whether the data is changes and execute the notification callback.
1377c804472Sopenharmony_ci    static void CheckAll()
1387c804472Sopenharmony_ci    {
1397c804472Sopenharmony_ci        std::list<std::pair<std::function<void(T)>, T>> pairs;
1407c804472Sopenharmony_ci        staticDataMutex.lock();
1417c804472Sopenharmony_ci        for (auto dataIter = dataMap.begin(); dataIter != dataMap.end(); ++dataIter) {
1427c804472Sopenharmony_ci            auto checkers = dataIter->second.Check();
1437c804472Sopenharmony_ci            pairs.insert(pairs.end(), checkers.begin(), checkers.end());
1447c804472Sopenharmony_ci        }
1457c804472Sopenharmony_ci        staticDataMutex.unlock();
1467c804472Sopenharmony_ci
1477c804472Sopenharmony_ci        for (auto pair : pairs) {
1487c804472Sopenharmony_ci            pair.first(pair.second);
1497c804472Sopenharmony_ci        }
1507c804472Sopenharmony_ci    }
1517c804472Sopenharmony_ci
1527c804472Sopenharmony_ciprivate:
1537c804472Sopenharmony_ci    T value;
1547c804472Sopenharmony_ci    bool isChanged;
1557c804472Sopenharmony_ci    T minValue;
1567c804472Sopenharmony_ci    T maxValue;
1577c804472Sopenharmony_ci    // map<thread id, pair<callback, detection period>>
1587c804472Sopenharmony_ci    std::map<std::thread::id, std::pair<std::function<void(T)>, uint32_t>> callBacks;
1597c804472Sopenharmony_ci    // map<thread id, current time tick>
1607c804472Sopenharmony_ci    std::map<std::thread::id, uint32_t> ticksMap;
1617c804472Sopenharmony_ci    static std::map<SharedDataType, SharedData> dataMap;
1627c804472Sopenharmony_ci    static std::mutex staticDataMutex;
1637c804472Sopenharmony_ci};
1647c804472Sopenharmony_ci
1657c804472Sopenharmony_citemplate<typename T> std::map<SharedDataType, SharedData<T>> SharedData<T>::dataMap;
1667c804472Sopenharmony_ci
1677c804472Sopenharmony_citemplate<typename T> std::mutex SharedData<T>::staticDataMutex;
1687c804472Sopenharmony_ci
1697c804472Sopenharmony_ci#endif // SHAREDDATA_H
170