diff --git a/tools/traff_assessment_tool/CMakeLists.txt b/tools/traff_assessment_tool/CMakeLists.txt index 833b68dd2..a5ee6f868 100644 --- a/tools/traff_assessment_tool/CMakeLists.txt +++ b/tools/traff_assessment_tool/CMakeLists.txt @@ -7,6 +7,8 @@ set(SRC map_widget.cpp map_widget.hpp points_controller_delegate_base.hpp + resumable_timer.cpp + resumable_timer.hpp traffic_drawer_delegate_base.hpp traffic_model.cpp traffic_model.hpp diff --git a/tools/traff_assessment_tool/mainwindow.cpp b/tools/traff_assessment_tool/mainwindow.cpp index 780506880..86aebee57 100644 --- a/tools/traff_assessment_tool/mainwindow.cpp +++ b/tools/traff_assessment_tool/mainwindow.cpp @@ -341,6 +341,7 @@ void MainWindow::CreateTrafficPanel() m_dockWidget->setMinimumWidth(400); } m_trafficPanel->SetStatus(true); + m_trafficPanel->GetTimer().Resume(); m_dockWidget->show(); } @@ -423,6 +424,7 @@ void MainWindow::OnPurgeExpiredMessages() void MainWindow::OnClearCache() { + m_trafficPanel->GetTimer().Reset(); m_framework.GetTrafficManager().Clear(); } diff --git a/tools/traff_assessment_tool/resumable_timer.cpp b/tools/traff_assessment_tool/resumable_timer.cpp new file mode 100644 index 000000000..a3e93d4d1 --- /dev/null +++ b/tools/traff_assessment_tool/resumable_timer.cpp @@ -0,0 +1,35 @@ +#include "traff_assessment_tool/resumable_timer.hpp" + +namespace base +{ +std::chrono::steady_clock::duration ResumableTimer::TimeElapsed() const +{ + if (m_isRunning) + return std::chrono::steady_clock::now() - m_startTime; + else + return m_prevTimeElapsed; +} + +void ResumableTimer::Pause() +{ + if (!m_isRunning) + return; + m_prevTimeElapsed = TimeElapsed(); + m_isRunning = false; +} + +void ResumableTimer::Resume() +{ + if (m_isRunning) + return; + m_startTime = std::chrono::steady_clock::now() - m_prevTimeElapsed; + m_prevTimeElapsed = std::chrono::steady_clock::duration::zero(); + m_isRunning = true; +} + +void ResumableTimer::Reset() +{ + m_startTime = std::chrono::steady_clock::now(); + m_prevTimeElapsed = std::chrono::steady_clock::duration::zero(); +} +} // namespace base diff --git a/tools/traff_assessment_tool/resumable_timer.hpp b/tools/traff_assessment_tool/resumable_timer.hpp new file mode 100644 index 000000000..f09a46ab3 --- /dev/null +++ b/tools/traff_assessment_tool/resumable_timer.hpp @@ -0,0 +1,81 @@ +#pragma once + +#include + +namespace base +{ +/** + * @brief A timer which can be paused and resumed. + * + * On creation, the timer is in paused state. + * + * Elapsed time can be queried in any state (running or paused). In running state, it will return + * the currently elapsed time, and the result will increase with each subsequent call. In paused + * state, it will return the time elapsed when the timer was last paused, and the result is stable + * between calls as long as the timer remains paused. + */ +class ResumableTimer +{ +public: + std::chrono::steady_clock::duration TimeElapsed() const; + + template + Duration TimeElapsedAs() const + { + return std::chrono::duration_cast(TimeElapsed()); + } + + double ElapsedSeconds() const { return TimeElapsedAs>().count(); } + uint64_t ElapsedMilliseconds() const { return TimeElapsedAs().count(); } + uint64_t ElapsedNanoseconds() const { return TimeElapsedAs().count(); } + + /** + * @brief Pauses the timer, i.e. freezes its current value and stops it from advancing further. + * + * Pausing an already paused timer is a no-op. + */ + void Pause(); + + /** + * @brief Resumes the timer, i.e. causes it to advance further from its previous value. + * + * Resuming a running timer is a no-op. + */ + void Resume(); + + /** + * @brief Resets the timer to zero. + * + * Resetting the timer will not change its paused/running state. That is, resetting a running + * timer will cause it to count upward from zero immediately, whereas resetting a paused timer + * will set its value to zero and keep it there until resumed. + */ + void Reset(); +private: + /** + * @brief The time at which the timer was last started. + * + * Valid only if the timer is running. + * + * When first starting a timer after it has been created or reset, this value is set to current + * time. When resuming a timer, this value us set to current time minus `m_prevTimeElapsed`, so + * that the timer value for a currently running timer is always the difference between this value + * and current time. + */ + std::chrono::steady_clock::time_point m_startTime; + + /** + * @brief Whether the timer is currently running. + */ + bool m_isRunning = false; + + /** + * @brief The time elapsed when the timer was last paused. + * + * Valid only if the timer is paused. + * + * Initially zero, reset to zero when the timer is reset or resumed. + */ + std::chrono::steady_clock::duration m_prevTimeElapsed = std::chrono::steady_clock::duration::zero(); +}; +} // namespace base diff --git a/tools/traff_assessment_tool/traffic_panel.cpp b/tools/traff_assessment_tool/traffic_panel.cpp index 483a306b6..c72898b6e 100644 --- a/tools/traff_assessment_tool/traffic_panel.cpp +++ b/tools/traff_assessment_tool/traffic_panel.cpp @@ -75,8 +75,9 @@ void TrafficPanel::SetStatus(bool inProgress, std::optional messageCount } else { + GetTimer().Pause(); if (messageCount) - m_status->setText(QString("Messages: %1").arg(messageCount.value())); + m_status->setText(QString("Messages: %1\tDecoded in %2 s").arg(messageCount.value()).arg(GetTimer().ElapsedSeconds())); m_progressBar->hide(); m_status->show(); } diff --git a/tools/traff_assessment_tool/traffic_panel.hpp b/tools/traff_assessment_tool/traffic_panel.hpp index 6c279cdae..a568d504a 100644 --- a/tools/traff_assessment_tool/traffic_panel.hpp +++ b/tools/traff_assessment_tool/traffic_panel.hpp @@ -1,5 +1,7 @@ #pragma once +#include "traff_assessment_tool/resumable_timer.hpp" + #include #include #include @@ -36,6 +38,7 @@ class TrafficPanel : public QWidget public: explicit TrafficPanel(QAbstractItemModel * trafficModel, QWidget * parent); + base::ResumableTimer & GetTimer() { return m_timer; } void SetStatus(bool inProgress, std::optional messageCount = std::nullopt); private: @@ -50,6 +53,7 @@ public slots: private: QTableView * m_table = Q_NULLPTR; QProgressBar * m_progressBar = Q_NULLPTR; + base::ResumableTimer m_timer; QLabel * m_status = Q_NULLPTR; }; } // namespace traffxml