Add progress reporter type

To log/report progress of long duration operations using given time period.
pull/3186/head
elsid 3 years ago
parent d8d16a52e1
commit bb26ba30b6
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40

@ -24,6 +24,7 @@ if (GTEST_FOUND AND GMOCK_FOUND)
misc/test_stringops.cpp
misc/test_endianness.cpp
misc/progressreporter.cpp
nifloader/testbulletnifloader.cpp

@ -0,0 +1,43 @@
#include <components/misc/progressreporter.hpp>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <chrono>
namespace
{
using namespace testing;
using namespace Misc;
struct ReportMock
{
MOCK_METHOD(void, call, (std::size_t, std::size_t), ());
};
struct Report
{
StrictMock<ReportMock>* mImpl;
void operator()(std::size_t provided, std::size_t expected)
{
mImpl->call(provided, expected);
}
};
TEST(MiscProgressReporterTest, shouldCallReportWhenPassedInterval)
{
StrictMock<ReportMock> report;
EXPECT_CALL(report, call(13, 42)).WillOnce(Return());
ProgressReporter reporter(std::chrono::steady_clock::duration(0), Report {&report});
reporter(13, 42);
}
TEST(MiscProgressReporterTest, shouldNotCallReportWhenIntervalIsNotPassed)
{
StrictMock<ReportMock> report;
EXPECT_CALL(report, call(13, 42)).Times(0);
ProgressReporter reporter(std::chrono::seconds(1000), Report {&report});
reporter(13, 42);
}
}

@ -0,0 +1,50 @@
#ifndef OPENMW_COMPONENTS_MISC_PROGRESSREPORTER_H
#define OPENMW_COMPONENTS_MISC_PROGRESSREPORTER_H
#include <algorithm>
#include <chrono>
#include <mutex>
#include <type_traits>
#include <utility>
namespace Misc
{
template <class Report>
class ProgressReporter
{
public:
explicit ProgressReporter(Report&& report = Report {})
: mReport(std::forward<Report>(report))
{}
explicit ProgressReporter(std::chrono::steady_clock::duration interval, Report&& report = Report {})
: mInterval(interval)
, mReport(std::forward<Report>(report))
{}
void operator()(std::size_t provided, std::size_t expected)
{
expected = std::max(expected, provided);
const bool shouldReport = [&]
{
const std::lock_guard lock(mMutex);
const auto now = std::chrono::steady_clock::now();
const auto left = mNextReport - now;
if (left.count() > 0 || provided == expected)
return false;
mNextReport += mInterval + left;
return true;
} ();
if (shouldReport)
mReport(provided, expected);
}
private:
const std::chrono::steady_clock::duration mInterval = std::chrono::seconds(1);
Report mReport;
std::mutex mMutex;
std::chrono::steady_clock::time_point mNextReport {std::chrono::steady_clock::now() + mInterval};
};
}
#endif
Loading…
Cancel
Save