mirror of https://github.com/OpenMW/openmw.git
Add progress reporter type
To log/report progress of long duration operations using given time period.pull/3186/head
parent
d8d16a52e1
commit
bb26ba30b6
@ -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…
Reference in New Issue