1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 Intel Corporation.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qdeadlinetimer.h"
41 #include "qdeadlinetimer_p.h"
42 #include "private/qnumeric_p.h"
43 
44 QT_BEGIN_NAMESPACE
45 
46 namespace {
47     class TimeReference
48     {
49         enum : unsigned {
50             umega = 1000 * 1000,
51             ugiga = umega * 1000
52         };
53 
54         enum : qint64 {
55             kilo = 1000,
56             mega = kilo * 1000,
57             giga = mega * 1000
58         };
59 
60     public:
61         enum RoundingStrategy {
62             RoundDown,
63             RoundUp,
64             RoundDefault = RoundDown
65         };
66 
67         static constexpr qint64 Min = std::numeric_limits<qint64>::min();
68         static constexpr qint64 Max = std::numeric_limits<qint64>::max();
69 
70         inline TimeReference(qint64 = 0, unsigned = 0);
71         inline void updateTimer(qint64 &, unsigned &);
72 
73         inline bool addNanoseconds(qint64);
74         inline bool addMilliseconds(qint64);
75         bool addSecsAndNSecs(qint64, qint64);
76 
77         inline bool subtract(const qint64, const unsigned);
78 
79         inline bool toMilliseconds(qint64 *, RoundingStrategy = RoundDefault) const;
80         inline bool toNanoseconds(qint64 *) const;
81 
82         inline void saturate(bool toMax);
83         static bool sign(qint64, qint64);
84 
85     private:
86         bool adjust(const qint64, const unsigned, qint64 = 0);
87 
88     private:
89         qint64 secs;
90         unsigned nsecs;
91     };
92 }
93 
TimeReference(qint64 t1,unsigned t2)94 inline TimeReference::TimeReference(qint64 t1, unsigned t2)
95     : secs(t1), nsecs(t2)
96 {
97 }
98 
updateTimer(qint64 & t1,unsigned & t2)99 inline void TimeReference::updateTimer(qint64 &t1, unsigned &t2)
100 {
101     t1 = secs;
102     t2 = nsecs;
103 }
104 
saturate(bool toMax)105 inline void TimeReference::saturate(bool toMax)
106 {
107     secs = toMax ? Max : Min;
108 }
109 
110 /*!
111  * \internal
112  *
113  * Determines the sign of a (seconds, nanoseconds) pair
114  * for differentiating overflow from underflow. It doesn't
115  * deal with equality as it shouldn't ever be called in that case.
116  *
117  * Returns true if the pair represents a positive time offset
118  * false otherwise.
119  */
sign(qint64 secs,qint64 nsecs)120 bool TimeReference::sign(qint64 secs, qint64 nsecs)
121 {
122     if (secs > 0) {
123         if (nsecs > 0)
124             return true;
125     } else {
126         if (nsecs < 0)
127             return false;
128     }
129 
130     // They are different in sign
131     secs += nsecs / giga;
132     if (secs > 0)
133         return true;
134     else if (secs < 0)
135         return false;
136 
137     // We should never get over|underflow out of
138     // the case: secs * giga == -nsecs
139     // So the sign of nsecs is the deciding factor
140     Q_ASSERT(nsecs % giga != 0);
141     return nsecs > 0;
142 }
143 
144 #if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
addNanoseconds(qint64 arg)145 inline bool TimeReference::addNanoseconds(qint64 arg)
146 {
147     return addSecsAndNSecs(arg / giga, arg % giga);
148 }
149 
addMilliseconds(qint64 arg)150 inline bool TimeReference::addMilliseconds(qint64 arg)
151 {
152     return addSecsAndNSecs(arg / kilo, (arg % kilo) * mega);
153 }
154 
155 /*!
156  * \internal
157  *
158  * Adds \a t1 addSecs seconds and \a addNSecs nanoseconds to the
159  * time reference. The arguments are normalized to seconds (qint64)
160  * and nanoseconds (unsigned) before the actual calculation is
161  * delegated to adjust(). If the nanoseconds are negative the
162  * owed second used for the normalization is passed on to adjust()
163  * as third argument.
164  *
165  * Returns true if operation was successful, false on over|underflow
166  */
addSecsAndNSecs(qint64 addSecs,qint64 addNSecs)167 bool TimeReference::addSecsAndNSecs(qint64 addSecs, qint64 addNSecs)
168 {
169     // Normalize the arguments
170     if (qAbs(addNSecs) >= giga) {
171         if (add_overflow<qint64>(addSecs, addNSecs / giga, &addSecs))
172             return false;
173 
174         addNSecs %= giga;
175     }
176 
177     if (addNSecs < 0)
178         return adjust(addSecs, ugiga - unsigned(-addNSecs), -1);
179 
180     return adjust(addSecs, unsigned(addNSecs));
181 }
182 
183 /*!
184  * \internal
185  *
186  * Adds \a t1 seconds and \a t2 nanoseconds to the internal members.
187  * Takes into account the additional \a carrySeconds we may owe or need to carry over.
188  *
189  * Returns true if operation was successful, false on over|underflow
190  */
adjust(const qint64 t1,const unsigned t2,qint64 carrySeconds)191 bool TimeReference::adjust(const qint64 t1, const unsigned t2, qint64 carrySeconds)
192 {
193     Q_STATIC_ASSERT(QDeadlineTimerNanosecondsInT2);
194     nsecs += t2;
195     if (nsecs >= ugiga) {
196         nsecs -= ugiga;
197         carrySeconds++;
198     }
199 
200     // We don't worry about the order of addition, because the result returned by
201     // callers of this function is unchanged regardless of us over|underflowing.
202     // If we do, we do so by no more than a second, thus saturating the timer to
203     // Forever has the same effect as if we did the arithmetic exactly and salvaged
204     // the overflow.
205     return !add_overflow<qint64>(secs, t1, &secs) && !add_overflow<qint64>(secs, carrySeconds, &secs);
206 }
207 
208 /*!
209  * \internal
210  *
211  * Subtracts \a t1 seconds and \a t2 nanoseconds from the time reference.
212  * When normalizing the nanoseconds to a positive number the owed seconds is
213  * passed as third argument to adjust() as the seconds may over|underflow
214  * if we do the calculation directly. There is little sense to check the
215  * seconds for over|underflow here in case we are going to need to carry
216  * over a second _after_ we add the nanoseconds.
217  *
218  * Returns true if operation was successful, false on over|underflow
219  */
subtract(const qint64 t1,const unsigned t2)220 inline bool TimeReference::subtract(const qint64 t1, const unsigned t2)
221 {
222     Q_ASSERT(t2 < ugiga);
223     return adjust(-t1, ugiga - t2, -1);
224 }
225 
226 /*!
227  * \internal
228  *
229  * Converts the time reference to milliseconds.
230  *
231  * Checks are done without making use of mul_overflow because it may
232  * not be implemented on some 32bit platforms.
233  *
234  * Returns true if operation was successful, false on over|underflow
235  */
toMilliseconds(qint64 * result,RoundingStrategy rounding) const236 inline bool TimeReference::toMilliseconds(qint64 *result, RoundingStrategy rounding) const
237 {
238     static constexpr qint64 maxSeconds = Max / kilo;
239     static constexpr qint64 minSeconds = Min / kilo;
240     if (secs > maxSeconds || secs < minSeconds)
241         return false;
242 
243     unsigned ns = rounding == RoundDown ? nsecs : nsecs + umega - 1;
244 
245     return !add_overflow<qint64>(secs * kilo, ns / umega, result);
246 }
247 
248 /*!
249  * \internal
250  *
251  * Converts the time reference to nanoseconds.
252  *
253  * Checks are done without making use of mul_overflow because it may
254  * not be implemented on some 32bit platforms.
255  *
256  * Returns true if operation was successful, false on over|underflow
257  */
toNanoseconds(qint64 * result) const258 inline bool TimeReference::toNanoseconds(qint64 *result) const
259 {
260     static constexpr qint64 maxSeconds = Max / giga;
261     static constexpr qint64 minSeconds = Min / giga;
262     if (secs > maxSeconds || secs < minSeconds)
263         return false;
264 
265     return !add_overflow<qint64>(secs * giga, nsecs, result);
266 }
267 #else
addNanoseconds(qint64 arg)268 inline bool TimeReference::addNanoseconds(qint64 arg)
269 {
270     return adjust(arg, 0);
271 }
272 
addMilliseconds(qint64 arg)273 inline bool TimeReference::addMilliseconds(qint64 arg)
274 {
275     static constexpr qint64 maxMilliseconds = Max / mega;
276     if (qAbs(arg) > maxMilliseconds)
277         return false;
278 
279     return addNanoseconds(arg * mega);
280 }
281 
addSecsAndNSecs(qint64 addSecs,qint64 addNSecs)282 inline bool TimeReference::addSecsAndNSecs(qint64 addSecs, qint64 addNSecs)
283 {
284     static constexpr qint64 maxSeconds = Max / giga;
285     static constexpr qint64 minSeconds = Min / giga;
286     if (addSecs > maxSeconds || addSecs < minSeconds || add_overflow<qint64>(addSecs * giga, addNSecs, &addNSecs))
287         return false;
288 
289     return addNanoseconds(addNSecs);
290 }
291 
adjust(const qint64 t1,const unsigned t2,qint64 carrySeconds)292 inline bool TimeReference::adjust(const qint64 t1, const unsigned t2, qint64 carrySeconds)
293 {
294     Q_STATIC_ASSERT(!QDeadlineTimerNanosecondsInT2);
295     Q_UNUSED(t2);
296     Q_UNUSED(carrySeconds);
297 
298     return !add_overflow<qint64>(secs, t1, &secs);
299 }
300 
subtract(const qint64 t1,const unsigned t2)301 inline bool TimeReference::subtract(const qint64 t1, const unsigned t2)
302 {
303     Q_UNUSED(t2);
304 
305     return addNanoseconds(-t1);
306 }
307 
toMilliseconds(qint64 * result,RoundingStrategy rounding) const308 inline bool TimeReference::toMilliseconds(qint64 *result, RoundingStrategy rounding) const
309 {
310     // Force QDeadlineTimer to treat the border cases as
311     // over|underflow and saturate the results returned to the user.
312     // We don't want to get valid milliseconds out of saturated timers.
313     if (secs == Max || secs == Min)
314         return false;
315 
316     *result = secs / mega;
317     if (rounding == RoundUp && secs > *result * mega)
318         (*result)++;
319 
320     return true;
321 }
322 
toNanoseconds(qint64 * result) const323 inline bool TimeReference::toNanoseconds(qint64 *result) const
324 {
325     *result = secs;
326     return true;
327 }
328 #endif
329 
330 /*!
331     \class QDeadlineTimer
332     \inmodule QtCore
333     \brief The QDeadlineTimer class marks a deadline in the future.
334     \since 5.8
335 
336     \reentrant
337     \ingroup tools
338 
339     The QDeadlineTimer class is usually used to calculate future deadlines and
340     verify whether the deadline has expired. QDeadlineTimer can also be used
341     for deadlines without expiration ("forever"). It forms a counterpart to
342     QElapsedTimer, which calculates how much time has elapsed since
343     QElapsedTimer::start() was called.
344 
345     QDeadlineTimer provides a more convenient API compared to
346     QElapsedTimer::hasExpired().
347 
348     The typical use-case for the class is to create a QDeadlineTimer before the
349     operation in question is started, and then use remainingTime() or
350     hasExpired() to determine whether to continue trying the operation.
351     QDeadlineTimer objects can be passed to functions being called to execute
352     this operation so they know how long to still operate.
353 
354     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 0
355 
356     Many QDeadlineTimer functions deal with time out values, which all are
357     measured in milliseconds. There are two special values, the same as many
358     other Qt functions named \c{waitFor} or similar:
359 
360     \list
361       \li 0: no time left, expired
362       \li -1: infinite time left, timer never expires
363     \endlist
364 
365     \section1 Reference Clocks
366 
367     QDeadlineTimer will use the same clock as QElapsedTimer (see
368     QElapsedTimer::clockType() and QElapsedTimer::isMonotonic()).
369 
370     \section1 Timer types
371 
372     Like QTimer, QDeadlineTimer can select among different levels of coarseness
373     on the timers. You can select precise timing by passing Qt::PreciseTimer to
374     the functions that set of change the timer, or you can select coarse timing
375     by passing Qt::CoarseTimer. Qt::VeryCoarseTimer is currently interpreted
376     the same way as Qt::CoarseTimer.
377 
378     This feature is dependent on support from the operating system: if the OS
379     does not support a coarse timer functionality, then QDeadlineTimer will
380     behave like Qt::PreciseTimer was passed.
381 
382     QDeadlineTimer defaults to Qt::CoarseTimer because on operating systems
383     that do support coarse timing, making timing calls to that clock source is
384     often much more efficient. The level of coarseness depends on the
385     operating system, but should be in the order of a couple of milliseconds.
386 
387     \section1 \c{std::chrono} Compatibility
388 
389     QDeadlineTimer is compatible with the \c{std::chrono} API from C++11 and
390     can be constructed from or compared to both \c{std::chrono::duration} and
391     \c{std::chrono::time_point} objects. In addition, it is fully compatible
392     with the time literals from C++14, which allow one to write code as:
393 
394     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 1
395 
396     As can be seen in the example above, QDeadlineTimer offers a templated
397     version of remainingTime() and deadline() that can be used to return
398     \c{std::chrono} objects.
399 
400     Note that comparing to \c{time_point} is not as efficient as comparing to
401     \c{duration}, since QDeadlineTimer may need to convert from its own
402     internal clock source to the clock source used by the \c{time_point} object.
403     Also note that, due to this conversion, the deadlines will not be precise,
404     so the following code is not expected to compare equally:
405 
406     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 2
407 
408     \sa QTime, QTimer, QDeadlineTimer, Qt::TimerType
409 */
410 
411 /*!
412     \enum QDeadlineTimer::ForeverConstant
413 
414     \value Forever      Used when creating a QDeadlineTimer to indicate the
415                         deadline should not expire
416 */
417 
418 /*!
419     \fn QDeadlineTimer::QDeadlineTimer(Qt::TimerType timerType)
420 
421     Constructs an expired QDeadlineTimer object. For this object,
422     remainingTime() will return 0.
423 
424     The timer type \a timerType may be ignored, since the timer is already
425     expired. Similarly, for optimization purposes, this function will not
426     attempt to obtain the current time and will use a value known to be in the
427     past. Therefore, deadline() may return an unexpected value and this object
428     cannot be used in calculation of how long it is overdue. If that
429     functionality is required, use QDeadlineTimer::current().
430 
431     \sa hasExpired(), remainingTime(), Qt::TimerType, current()
432 */
433 
434 /*!
435     \fn QDeadlineTimer::QDeadlineTimer(ForeverConstant, Qt::TimerType timerType)
436 
437     QDeadlineTimer objects created with ForeverConstant never expire.
438     For such objects, remainingTime() will return -1, deadline() will return the
439     maximum value, and isForever() will return true.
440 
441     The timer type \a timerType may be ignored, since the timer will never
442     expire.
443 
444     \sa ForeverConstant, hasExpired(), isForever(), remainingTime(), timerType()
445 */
446 
447 /*!
448     Constructs a QDeadlineTimer object with an expiry time of \a msecs msecs
449     from the moment of the creation of this object, if msecs is positive. If \a
450     msecs is zero, this QDeadlineTimer will be marked as expired, causing
451     remainingTime() to return zero and deadline() to return an indeterminate
452     time point in the past. If \a msecs is -1, the timer will be set to never
453     expire, causing remainingTime() to return -1 and deadline() to return the
454     maximum value.
455 
456     The QDeadlineTimer object will be constructed with the specified timer \a type.
457 
458     For optimization purposes, if \a msecs is zero, this function may skip
459     obtaining the current time and may instead use a value known to be in the
460     past. If that happens, deadline() may return an unexpected value and this
461     object cannot be used in calculation of how long it is overdue. If that
462     functionality is required, use QDeadlineTimer::current() and add time to
463     it.
464 
465     \sa hasExpired(), isForever(), remainingTime(), setRemainingTime()
466 */
QDeadlineTimer(qint64 msecs,Qt::TimerType type)467 QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) noexcept
468     : t2(0)
469 {
470     setRemainingTime(msecs, type);
471 }
472 
473 /*!
474     \fn template <class Clock, class Duration> QDeadlineTimer::QDeadlineTimer(std::chrono::time_point<Clock, Duration> deadline, Qt::TimerType type)
475 
476     Constructs a QDeadlineTimer object with a deadline at \a deadline time
477     point, converting from the clock source \c{Clock} to Qt's internal clock
478     source (see QElapsedTimer::clockType()).
479 
480     If \a deadline is in the past, this QDeadlineTimer object is set to
481     expired, whereas if \a deadline is equal to \c{Duration::max()}, then this
482     object is set to never expire.
483 
484     The QDeadlineTimer object will be constructed with the specified timer \a type.
485 
486     \sa hasExpired(), isForever(), remainingTime(), setDeadline()
487 */
488 
489 /*!
490     \fn template <class Rep, class Period> QDeadlineTimer::QDeadlineTimer(std::chrono::duration<Rep, Period> remaining, Qt::TimerType type)
491 
492     Constructs a QDeadlineTimer object with a remaining time of \a remaining.
493     If \a remaining is zero or negative, this QDeadlineTimer object will be
494     mark as expired, whereas if \a remaining is equal to \c{duration::max()},
495     the object will be set to never expire.
496 
497     The QDeadlineTimer object will be constructed with the specified timer \a type.
498 
499     This constructor can be used with C++14's user-defined literals for time, such as in:
500 
501     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 3
502 
503     For optimization purposes, if \a remaining is zero or negative, this
504     function may skip obtaining the current time and may instead use a value
505     known to be in the past. If that happens, deadline() may return an
506     unexpected value and this object cannot be used in calculation of how long
507     it is overdue. If that functionality is required, use
508     QDeadlineTimer::current() and add time to it.
509 
510     \sa hasExpired(), isForever(), remainingTime(), setRemainingTime()
511 */
512 
513 /*!
514     \fn template <class Clock, class Duration> void QDeadlineTimer::setDeadline(std::chrono::time_point<Clock, Duration> deadline, Qt::TimerType type)
515 
516     Sets this QDeadlineTimer to the deadline marked by \a deadline time
517     point, converting from the clock source \c{Clock} to Qt's internal clock
518     source (see QElapsedTimer::clockType()).
519 
520     If \a deadline is in the past, this QDeadlineTimer object is set to
521     expired, whereas if \a deadline is equal to \c{Duration::max()}, then this
522     object is set to never expire.
523 
524     The timer type for this QDeadlineTimer object will be set to the specified \a type.
525 
526     \sa hasExpired(), isForever(), remainingTime(),
527 */
528 
529 /*!
530     Sets the remaining time for this QDeadlineTimer object to \a msecs
531     milliseconds from now, if \a msecs has a positive value. If \a msecs is
532     zero, this QDeadlineTimer object will be marked as expired, whereas a value
533     of -1 will set it to never expire.
534 
535     The timer type for this QDeadlineTimer object will be set to the specified \a timerType.
536 
537     \sa setPreciseRemainingTime(), hasExpired(), isForever(), remainingTime()
538 */
setRemainingTime(qint64 msecs,Qt::TimerType timerType)539 void QDeadlineTimer::setRemainingTime(qint64 msecs, Qt::TimerType timerType) noexcept
540 {
541     if (msecs == -1) {
542         *this = QDeadlineTimer(Forever, timerType);
543         return;
544     }
545 
546     *this = current(timerType);
547 
548     TimeReference ref(t1, t2);
549     if (!ref.addMilliseconds(msecs))
550         ref.saturate(msecs > 0);
551     ref.updateTimer(t1, t2);
552 }
553 
554 /*!
555     Sets the remaining time for this QDeadlineTimer object to \a secs seconds
556     plus \a nsecs nanoseconds from now, if \a secs has a positive value. If \a
557     secs is -1, this QDeadlineTimer will be set it to never expire. If both
558     parameters are zero, this QDeadlineTimer will be marked as expired.
559 
560     The timer type for this QDeadlineTimer object will be set to the specified
561     \a timerType.
562 
563     \sa setRemainingTime(), hasExpired(), isForever(), remainingTime()
564 */
setPreciseRemainingTime(qint64 secs,qint64 nsecs,Qt::TimerType timerType)565 void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::TimerType timerType) noexcept
566 {
567     if (secs == -1) {
568         *this = QDeadlineTimer(Forever, timerType);
569         return;
570     }
571 
572     *this = current(timerType);
573     TimeReference ref(t1, t2);
574     if (!ref.addSecsAndNSecs(secs, nsecs))
575         ref.saturate(TimeReference::sign(secs, nsecs));
576     ref.updateTimer(t1, t2);
577 }
578 
579 /*!
580     \overload
581     \fn template <class Rep, class Period> void QDeadlineTimer::setRemainingTime(std::chrono::duration<Rep, Period> remaining, Qt::TimerType type)
582 
583     Sets the remaining time for this QDeadlineTimer object to \a remaining. If
584     \a remaining is zero or negative, this QDeadlineTimer object will be mark
585     as expired, whereas if \a remaining is equal to \c{duration::max()}, the
586     object will be set to never expire.
587 
588     The timer type for this QDeadlineTimer object will be set to the specified \a type.
589 
590     This function can be used with C++14's user-defined literals for time, such as in:
591 
592     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 4
593 
594     \note Qt detects the necessary C++14 compiler support by way of the feature
595     test recommendations from
596     \l{https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations}
597     {C++ Committee's Standing Document 6}.
598 
599     \sa setDeadline(), remainingTime(), hasExpired(), isForever()
600 */
601 
602 /*!
603     \fn bool QDeadlineTimer::isForever() const
604 
605     Returns true if this QDeadlineTimer object never expires, false otherwise.
606     For timers that never expire, remainingTime() always returns -1 and
607     deadline() returns the maximum value.
608 
609     \sa ForeverConstant, hasExpired(), remainingTime()
610 */
611 
612 /*!
613     Returns true if this QDeadlineTimer object has expired, false if there
614     remains time left. For objects that have expired, remainingTime() will
615     return zero and deadline() will return a time point in the past.
616 
617     QDeadlineTimer objects created with the \l {ForeverConstant} never expire
618     and this function always returns false for them.
619 
620     \sa isForever(), remainingTime()
621 */
hasExpired() const622 bool QDeadlineTimer::hasExpired() const noexcept
623 {
624     if (isForever())
625         return false;
626     return *this <= current(timerType());
627 }
628 
629 /*!
630     \fn Qt::TimerType QDeadlineTimer::timerType() const
631 
632     Returns the timer type is active for this object.
633 
634     \sa setTimerType()
635 */
636 
637 /*!
638     Changes the timer type for this object to \a timerType.
639 
640     The behavior for each possible value of \a timerType is operating-system
641     dependent. Qt::PreciseTimer will use the most precise timer that Qt can
642     find, with resolution of 1 millisecond or better, whereas QDeadlineTimer
643     will try to use a more coarse timer for Qt::CoarseTimer and
644     Qt::VeryCoarseTimer.
645 
646     \sa Qt::TimerType
647  */
setTimerType(Qt::TimerType timerType)648 void QDeadlineTimer::setTimerType(Qt::TimerType timerType)
649 {
650     type = timerType;
651 }
652 
653 /*!
654     Returns the remaining time in this QDeadlineTimer object in milliseconds.
655     If the timer has already expired, this function will return zero and it is
656     not possible to obtain the amount of time overdue with this function (to do
657     that, see deadline()). If the timer was set to never expire, this function
658     returns -1.
659 
660     This function is suitable for use in Qt APIs that take a millisecond
661     timeout, such as the many \l QIODevice \c waitFor functions or the timed
662     lock functions in \l QMutex, \l QWaitCondition, \l QSemaphore, or
663     \l QReadWriteLock. For example:
664 
665     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 5
666 
667     \sa remainingTimeNSecs(), isForever(), hasExpired()
668 */
remainingTime() const669 qint64 QDeadlineTimer::remainingTime() const noexcept
670 {
671     if (isForever())
672         return -1;
673 
674     QDeadlineTimer now = current(timerType());
675     TimeReference ref(t1, t2);
676 
677     qint64 msecs;
678     if (!ref.subtract(now.t1, now.t2))
679         return 0;   // We can only underflow here
680 
681     // If we fail the conversion, t1 < now.t1 means we underflowed,
682     // thus the deadline had long expired
683     if (!ref.toMilliseconds(&msecs, TimeReference::RoundUp))
684         return t1 < now.t1 ? 0 : -1;
685 
686     return msecs < 0 ? 0 : msecs;
687 }
688 
689 /*!
690     Returns the remaining time in this QDeadlineTimer object in nanoseconds. If
691     the timer has already expired, this function will return zero and it is not
692     possible to obtain the amount of time overdue with this function. If the
693     timer was set to never expire, this function returns -1.
694 
695     \sa remainingTime(), isForever(), hasExpired()
696 */
remainingTimeNSecs() const697 qint64 QDeadlineTimer::remainingTimeNSecs() const noexcept
698 {
699     if (isForever())
700         return -1;
701     qint64 raw = rawRemainingTimeNSecs();
702     return raw < 0 ? 0 : raw;
703 }
704 
705 /*!
706     \internal
707     Same as remainingTimeNSecs, but may return negative remaining times. Does
708     not deal with Forever. In case of underflow the result is saturated to
709     the minimum possible value, on overflow  - the maximum possible value.
710 */
rawRemainingTimeNSecs() const711 qint64 QDeadlineTimer::rawRemainingTimeNSecs() const noexcept
712 {
713     QDeadlineTimer now = current(timerType());
714     TimeReference ref(t1, t2);
715 
716     qint64 nsecs;
717     if (!ref.subtract(now.t1, now.t2))
718         return TimeReference::Min;  // We can only underflow here
719 
720     // If we fail the conversion, t1 < now.t1 means we underflowed,
721     // thus the deadline had long expired
722     if (!ref.toNanoseconds(&nsecs))
723         return t1 < now.t1 ? TimeReference::Min : TimeReference::Max;
724     return nsecs;
725 }
726 
727 /*!
728     Returns the absolute time point for the deadline stored in QDeadlineTimer
729     object, calculated in milliseconds relative to the reference clock, the
730     same as QElapsedTimer::msecsSinceReference(). The value will be in the past
731     if this QDeadlineTimer has expired.
732 
733     If this QDeadlineTimer never expires, this function returns
734     \c{std::numeric_limits<qint64>::max()}.
735 
736     This function can be used to calculate the amount of time a timer is
737     overdue, by subtracting QDeadlineTimer::current() or
738     QElapsedTimer::msecsSinceReference(), as in the following example:
739 
740     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 6
741 
742     \note Timers that were created as expired have an indetermine time point in
743     the past as their deadline, so the above calculation may not work.
744 
745     \sa remainingTime(), deadlineNSecs(), setDeadline()
746 */
deadline() const747 qint64 QDeadlineTimer::deadline() const noexcept
748 {
749     if (isForever())
750         return TimeReference::Max;
751 
752     qint64 result;
753     if (!TimeReference(t1, t2).toMilliseconds(&result))
754         return t1 < 0 ? TimeReference::Min : TimeReference::Max;
755 
756     return result;
757 }
758 
759 /*!
760     Returns the absolute time point for the deadline stored in QDeadlineTimer
761     object, calculated in nanoseconds relative to the reference clock, the
762     same as QElapsedTimer::msecsSinceReference(). The value will be in the past
763     if this QDeadlineTimer has expired.
764 
765     If this QDeadlineTimer never expires or the number of nanoseconds until the
766     deadline can't be accommodated in the return type, this function returns
767     \c{std::numeric_limits<qint64>::max()}.
768 
769     This function can be used to calculate the amount of time a timer is
770     overdue, by subtracting QDeadlineTimer::current(), as in the following
771     example:
772 
773     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 7
774 
775     \note Timers that were created as expired have an indetermine time point in
776     the past as their deadline, so the above calculation may not work.
777 
778     \sa remainingTime(), deadlineNSecs()
779 */
deadlineNSecs() const780 qint64 QDeadlineTimer::deadlineNSecs() const noexcept
781 {
782     if (isForever())
783         return TimeReference::Max;
784 
785     qint64 result;
786     if (!TimeReference(t1, t2).toNanoseconds(&result))
787         return t1 < 0 ? TimeReference::Min : TimeReference::Max;
788 
789     return result;
790 }
791 
792 /*!
793     Sets the deadline for this QDeadlineTimer object to be the \a msecs
794     absolute time point, counted in milliseconds since the reference clock (the
795     same as QElapsedTimer::msecsSinceReference()), and the timer type to \a
796     timerType. If the value is in the past, this QDeadlineTimer will be marked
797     as expired.
798 
799     If \a msecs is \c{std::numeric_limits<qint64>::max()} or the deadline is
800     beyond a representable point in the future, this QDeadlineTimer will be set
801     to never expire.
802 
803     \sa setPreciseDeadline(), deadline(), deadlineNSecs(), setRemainingTime()
804 */
setDeadline(qint64 msecs,Qt::TimerType timerType)805 void QDeadlineTimer::setDeadline(qint64 msecs, Qt::TimerType timerType) noexcept
806 {
807     if (msecs == TimeReference::Max) {
808         *this = QDeadlineTimer(Forever, timerType);
809         return;
810     }
811 
812     type = timerType;
813 
814     TimeReference ref;
815     if (!ref.addMilliseconds(msecs))
816         ref.saturate(msecs > 0);
817     ref.updateTimer(t1, t2);
818 }
819 
820 /*!
821     Sets the deadline for this QDeadlineTimer object to be \a secs seconds and
822     \a nsecs nanoseconds since the reference clock epoch (the same as
823     QElapsedTimer::msecsSinceReference()), and the timer type to \a timerType.
824     If the value is in the past, this QDeadlineTimer will be marked as expired.
825 
826     If \a secs or \a nsecs is \c{std::numeric_limits<qint64>::max()}, this
827     QDeadlineTimer will be set to never expire. If \a nsecs is more than 1
828     billion nanoseconds (1 second), then \a secs will be adjusted accordingly.
829 
830     \sa setDeadline(), deadline(), deadlineNSecs(), setRemainingTime()
831 */
setPreciseDeadline(qint64 secs,qint64 nsecs,Qt::TimerType timerType)832 void QDeadlineTimer::setPreciseDeadline(qint64 secs, qint64 nsecs, Qt::TimerType timerType) noexcept
833 {
834     type = timerType;
835 
836     // We don't pass the seconds to the constructor, because we don't know
837     // at this point if t1 holds the seconds or nanoseconds; it's platform specific.
838     TimeReference ref;
839     if (!ref.addSecsAndNSecs(secs, nsecs))
840         ref.saturate(TimeReference::sign(secs, nsecs));
841     ref.updateTimer(t1, t2);
842 }
843 
844 /*!
845     Returns a QDeadlineTimer object whose deadline is extended from \a dt's
846     deadline by \a nsecs nanoseconds. If \a dt was set to never expire, this
847     function returns a QDeadlineTimer that will not expire either.
848 
849     \note if \a dt was created as expired, its deadline is indeterminate and
850     adding an amount of time may or may not cause it to become unexpired.
851 */
addNSecs(QDeadlineTimer dt,qint64 nsecs)852 QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcept
853 {
854     if (dt.isForever())
855         return dt;
856 
857     TimeReference ref(dt.t1, dt.t2);
858     if (!ref.addNanoseconds(nsecs))
859         ref.saturate(nsecs > 0);
860     ref.updateTimer(dt.t1, dt.t2);
861 
862     return dt;
863 }
864 
865 /*!
866     \fn QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType)
867 
868     Returns a QDeadlineTimer that is expired but is guaranteed to contain the
869     current time. Objects created by this function can participate in the
870     calculation of how long a timer is overdue, using the deadline() function.
871 
872     The QDeadlineTimer object will be constructed with the specified \a timerType.
873 */
874 
875 /*!
876     \fn bool operator==(QDeadlineTimer d1, QDeadlineTimer d2)
877     \relates QDeadlineTimer
878 
879     Returns true if the deadline on \a d1 and the deadline in \a d2 are the
880     same, false otherwise. The timer type used to create the two deadlines is
881     ignored. This function is equivalent to:
882 
883     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 8
884 
885     \note comparing QDeadlineTimer objects with different timer types is
886     not supported and may result in unpredictable behavior.
887 */
888 
889 /*!
890     \fn bool operator!=(QDeadlineTimer d1, QDeadlineTimer d2)
891     \relates QDeadlineTimer
892 
893     Returns true if the deadline on \a d1 and the deadline in \a d2 are
894     diferent, false otherwise. The timer type used to create the two deadlines
895     is ignored. This function is equivalent to:
896 
897     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 9
898 
899     \note comparing QDeadlineTimer objects with different timer types is
900     not supported and may result in unpredictable behavior.
901 */
902 
903 /*!
904     \fn bool operator<(QDeadlineTimer d1, QDeadlineTimer d2)
905     \relates QDeadlineTimer
906 
907     Returns true if the deadline on \a d1 is earlier than the deadline in \a
908     d2, false otherwise. The timer type used to create the two deadlines is
909     ignored. This function is equivalent to:
910 
911     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 10
912 
913     \note comparing QDeadlineTimer objects with different timer types is
914     not supported and may result in unpredictable behavior.
915 */
916 
917 /*!
918     \fn bool operator<=(QDeadlineTimer d1, QDeadlineTimer d2)
919     \relates QDeadlineTimer
920 
921     Returns true if the deadline on \a d1 is earlier than or the same as the
922     deadline in \a d2, false otherwise. The timer type used to create the two
923     deadlines is ignored. This function is equivalent to:
924 
925     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 11
926 
927     \note comparing QDeadlineTimer objects with different timer types is
928     not supported and may result in unpredictable behavior.
929 */
930 
931 /*!
932     \fn bool operator>(QDeadlineTimer d1, QDeadlineTimer d2)
933     \relates QDeadlineTimer
934 
935     Returns true if the deadline on \a d1 is later than the deadline in \a
936     d2, false otherwise. The timer type used to create the two deadlines is
937     ignored. This function is equivalent to:
938 
939     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 12
940 
941     \note comparing QDeadlineTimer objects with different timer types is
942     not supported and may result in unpredictable behavior.
943 */
944 
945 /*!
946     \fn bool operator>=(QDeadlineTimer d1, QDeadlineTimer d2)
947     \relates QDeadlineTimer
948 
949     Returns true if the deadline on \a d1 is later than or the same as the
950     deadline in \a d2, false otherwise. The timer type used to create the two
951     deadlines is ignored. This function is equivalent to:
952 
953     \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 13
954 
955     \note comparing QDeadlineTimer objects with different timer types is
956     not supported and may result in unpredictable behavior.
957 */
958 
959 /*!
960     \fn QDeadlineTimer operator+(QDeadlineTimer dt, qint64 msecs)
961     \relates QDeadlineTimer
962 
963     Returns a QDeadlineTimer object whose deadline is \a msecs later than the
964     deadline stored in \a dt. If \a dt is set to never expire, this function
965     returns a QDeadlineTimer that does not expire either.
966 
967     To add times of precision greater than 1 millisecond, use addNSecs().
968 */
969 
operator +(QDeadlineTimer dt,qint64 msecs)970 QDeadlineTimer operator+(QDeadlineTimer dt, qint64 msecs)
971 {
972     if (dt.isForever())
973         return dt;
974 
975     TimeReference ref(dt.t1, dt.t2);
976     if (!ref.addMilliseconds(msecs))
977         ref.saturate(msecs > 0);
978     ref.updateTimer(dt.t1, dt.t2);
979 
980     return dt;
981 }
982 
983 /*!
984     \fn QDeadlineTimer operator+(qint64 msecs, QDeadlineTimer dt)
985     \relates QDeadlineTimer
986 
987     Returns a QDeadlineTimer object whose deadline is \a msecs later than the
988     deadline stored in \a dt. If \a dt is set to never expire, this function
989     returns a QDeadlineTimer that does not expire either.
990 
991     To add times of precision greater than 1 millisecond, use addNSecs().
992 */
993 
994 /*!
995     \fn QDeadlineTimer operator-(QDeadlineTimer dt, qint64 msecs)
996     \relates QDeadlineTimer
997 
998     Returns a QDeadlineTimer object whose deadline is \a msecs before the
999     deadline stored in \a dt. If \a dt is set to never expire, this function
1000     returns a QDeadlineTimer that does not expire either.
1001 
1002     To subtract times of precision greater than 1 millisecond, use addNSecs().
1003 */
1004 
1005 /*!
1006     \fn QDeadlineTimer &QDeadlineTimer::operator+=(qint64 msecs)
1007 
1008     Extends this QDeadlineTimer object by \a msecs milliseconds and returns
1009     itself. If this object is set to never expire, this function does nothing.
1010 
1011     To add times of precision greater than 1 millisecond, use addNSecs().
1012 */
1013 
1014 /*!
1015     \fn QDeadlineTimer &QDeadlineTimer::operator-=(qint64 msecs)
1016 
1017     Shortens this QDeadlineTimer object by \a msecs milliseconds and returns
1018     itself. If this object is set to never expire, this function does nothing.
1019 
1020     To subtract times of precision greater than 1 millisecond, use addNSecs().
1021 */
1022 
1023 /*!
1024   \fn void QDeadlineTimer::swap(QDeadlineTimer &other)
1025 
1026   Swaps this deadline timer with the \a other deadline timer.
1027  */
1028 
1029 /*!
1030   \fn template <class Clock, class Duration> QDeadlineTimer & QDeadlineTimer::operator=(std::chrono::time_point<Clock, Duration> deadline_)
1031 
1032   Assigns \a deadline_ to this deadline timer.
1033  */
1034 
1035 /*!
1036   \fn template <class Rep, class Period> QDeadlineTimer & QDeadlineTimer::operator=(std::chrono::duration<Rep, Period> remaining)
1037 
1038   Sets this deadline timer to the \a remaining time.
1039  */
1040 
1041 /*!
1042   \fn std::chrono::nanoseconds QDeadlineTimer::remainingTimeAsDuration() const
1043 
1044   Returns the time remaining before the deadline.
1045  */
1046 
1047 /*!
1048   \fn QPair<qint64, unsigned> QDeadlineTimer::_q_data() const
1049   \internal
1050 */
1051 
1052 // the rest of the functions are in qelapsedtimer_xxx.cpp
1053 
1054 QT_END_NAMESPACE
1055