From e80faf3db61ca9c701cd86876e3bce8e33226576 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 17 Oct 2016 13:00:04 +0200 Subject: QTimer: don't circumvent safety net By templating on the types and unconditionally using duration_cast to coerce the duration into a milliseconds, we violate a principal design rule of , namely that non- narrowing conversions are implicit, but narrowing conversions need duration_cast. By accepting any duration, we allow non- sensical code such as QTimer::singleShot(10us, ...) to compile, which is misleading, since it's actually a zero- timeout timer. Overloading a non-template with a template also has adverse effects: it breaks qOverload(). Fix by replacing the function templates with functions that just take std::chrono::milliseconds. This way, benign code such as QTimer::singleShot(10s, ...) QTimer::singleShot(10min, ...) QTimer::singleShot(1h, ...) work as expected, but attempts to use sub-millisecond resolution fails to compile / needs an explicit user- provided duration_cast. To allow future extension to more precise timers, forcibly inline the functions, so they don't partake in the ABI of the class and we can later support sub-millisecond resolution by simply taking micro- or nano- instead of milliseconds. Change-Id: I12c9a98bdabefcd8ec18a9eb09f87ad908d889de Reviewed-by: Thiago Macieira --- tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp index 28df01cc16..fe97695d19 100644 --- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp +++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp @@ -216,6 +216,16 @@ void tst_QTimer::remainingTimeDuringActivation() } } +namespace { + +#if QT_HAS_INCLUDE() + template + std::chrono::milliseconds to_ms(T t) + { return std::chrono::duration_cast(t); } +#endif + +} // unnamed namespace + void tst_QTimer::basic_chrono() { #if !QT_HAS_INCLUDE() @@ -225,7 +235,7 @@ void tst_QTimer::basic_chrono() using namespace std::chrono; TimerHelper helper; QTimer timer; - timer.setInterval(nanoseconds(0)); + timer.setInterval(to_ms(nanoseconds(0))); timer.start(); QCOMPARE(timer.intervalAsDuration().count(), milliseconds::rep(0)); QCOMPARE(timer.remainingTimeAsDuration().count(), milliseconds::rep(0)); @@ -248,7 +258,7 @@ void tst_QTimer::basic_chrono() QVERIFY(helper.count > oldCount); helper.count = 0; - timer.start(microseconds(200000)); + timer.start(to_ms(microseconds(200000))); QCOMPARE(timer.intervalAsDuration().count(), milliseconds::rep(200)); QTest::qWait(50); QCOMPARE(helper.count, 0); @@ -864,7 +874,7 @@ void tst_QTimer::singleShot_chrono() QCOMPARE(nhelper.count, 1); int count = 0; - QTimer::singleShot(microseconds(0), CountedStruct(&count)); + QTimer::singleShot(to_ms(microseconds(0)), CountedStruct(&count)); QCoreApplication::processEvents(); QCOMPARE(count, 1); -- cgit v1.2.3