From 94bddf23c9caa323017264e9b8f4f3d354a2553e Mon Sep 17 00:00:00 2001 From: zynfly Date: Mon, 27 Dec 2021 23:16:23 +0800 Subject: [PATCH] Init Commit --- .gitignore | 2 ++ CMakeLists.txt | 25 ++++++++++++++ RateSeveral.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ RateSeveral.h | 52 +++++++++++++++++++++++++++++ main.cpp | 21 ++++++++++++ 5 files changed, 187 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 RateSeveral.cpp create mode 100644 RateSeveral.h create mode 100644 main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4ce3357 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea/ +cmake-build-*/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0ef177b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.21) +project(RateSeveral) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + + +find_package(Qt5 COMPONENTS + Core + REQUIRED) + +add_executable(RateSeveral main.cpp RateSeveral.cpp RateSeveral.h) +target_link_libraries(RateSeveral + Qt5::Core + ) + +if (WIN32 AND MSVC) + set(QT_INSTALL_PATH "${CMAKE_PREFIX_PATH}") + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND + "${QT_INSTALL_PATH}/bin/windeployqt.exe" + "$") +endif () diff --git a/RateSeveral.cpp b/RateSeveral.cpp new file mode 100644 index 0000000..4274dfa --- /dev/null +++ b/RateSeveral.cpp @@ -0,0 +1,87 @@ +// +// Created by fly on 2021/12/27. +// + +#include "RateSeveral.h" +#include +#include + + +RateSeveral::RateSeveral(QObject *parent) : + QObject(parent), + timer(this) { + connect(&timer, SIGNAL(timeout()), this, SLOT(onTimerTimeout())); +} + +void RateSeveral::setTimerInterval(qint32 second) { + timer.start(second * 1000); + auto a = timer.isActive(); +} + +void RateSeveral::addRateInterval(quint32 second) { + if (vInterval.end() == std::find(vInterval.begin(), vInterval.end(), second)) { + intervalLock.lockForWrite(); + vInterval.push_back(second); + intervalLock.unlock(); + } +} + +void RateSeveral::removeRateInterval(quint32 second) { + auto iter = std::find(vInterval.begin(), vInterval.end(), second); + if (vInterval.end() != iter) { + intervalLock.lockForWrite(); + vInterval.erase(iter); + intervalLock.unlock(); + } +} + +void RateSeveral::record(quint32 val) { + auto timestamp = QDateTime::currentSecsSinceEpoch(); + auto expected = recordTimestamp.loadAcquire(); + if (timestamp != expected && recordTimestamp.testAndSetAcquire(expected, timestamp)) { + listLock.lockForWrite(); + recordList.push_back({timestamp, 0}); + listLock.unlock(); + } + recordList.last().second.fetchAndAddAcquire(val); +} + + +void RateSeveral::onTimerTimeout() { + intervalLock.lockForRead(); + auto interval = vInterval; + intervalLock.unlock(); + auto timestamp = QDateTime::currentSecsSinceEpoch(); + quint32 maxInterval = 0; + auto eraseIter = recordList.end(); + for (auto val: interval) { + auto lastTimestamp = timestamp - val - 1; + quint32 sum = 0; + listLock.lockForRead(); + auto iter = recordList.begin(); + for (; iter != recordList.end() && iter->first > lastTimestamp; ++iter) { + sum += iter->second; + } + listLock.unlock(); + + if (val > maxInterval) { + maxInterval = val; + eraseIter = iter; + } + emit RateSignals(val, sum); + } + if (eraseIter != recordList.end() && + (maxListSize ? maxListSize > recordList.size() : maxInterval * 2 > recordList.size())) { + listLock.lockForWrite(); + recordList.erase(eraseIter, recordList.end()); + listLock.unlock(); + } +} + +quint32 RateSeveral::getMaxListSize() const { + return maxListSize; +} + +void RateSeveral::setMaxListSize(quint32 maxSize) { + RateSeveral::maxListSize = maxSize; +} diff --git a/RateSeveral.h b/RateSeveral.h new file mode 100644 index 0000000..be19e47 --- /dev/null +++ b/RateSeveral.h @@ -0,0 +1,52 @@ +// +// Created by fly on 2021/12/27. +// + +#ifndef RATESEVERAL_RATESEVERAL_H +#define RATESEVERAL_RATESEVERAL_H + +#include +#include +#include +#include +#include +#include +#include + +class RateSeveral : public QObject { +Q_OBJECT +public: + explicit RateSeveral(QObject *parent = nullptr); + + void setTimerInterval(qint32 second); + + void addRateInterval(quint32 second); + + void removeRateInterval(quint32 second); + + void record(quint32 val = 1); + + quint32 getMaxListSize() const; + + void setMaxListSize(quint32 maxSize); + +signals: + + void RateSignals(quint32 interval, quint32 rate); + +protected slots: + + void onTimerTimeout(); + +protected: + QReadWriteLock intervalLock; + QReadWriteLock listLock; + quint32 maxListSize{1000}; + QTimer timer; + QVector vInterval; + QList>> recordList; + QAtomicInteger recordTimestamp; +}; + + +#endif //RATESEVERAL_RATESEVERAL_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..5e72b1f --- /dev/null +++ b/main.cpp @@ -0,0 +1,21 @@ +#include +#include +#include +#include "RateSeveral.h" + +int main(int argc, char *argv[]) { + QCoreApplication a(argc, argv); + RateSeveral rateSeveral; + rateSeveral.addRateInterval(1); + rateSeveral.addRateInterval(10); + rateSeveral.addRateInterval(60); + rateSeveral.addRateInterval(3600); + rateSeveral.setTimerInterval(1); + QObject::connect(&rateSeveral, &RateSeveral::RateSignals, [](quint32 interval, quint32 rate) { + qInfo() << interval << "\t" << rate; + }); + + rateSeveral.record(100); + + return QCoreApplication::exec(); +}