File indexing completed on 2026-05-17 08:20:10
0001
0002
0003
0004 #ifndef QDEADLINETIMER_H
0005 #define QDEADLINETIMER_H
0006
0007 #include <QtCore/qmetatype.h>
0008 #include <QtCore/qnamespace.h>
0009
0010 #ifdef max
0011
0012 # undef max
0013 #endif
0014
0015 #include <limits>
0016
0017 #include <chrono>
0018
0019 QT_BEGIN_NAMESPACE
0020
0021 class Q_CORE_EXPORT QDeadlineTimer
0022 {
0023 public:
0024 enum class ForeverConstant { Forever };
0025 static constexpr ForeverConstant Forever = ForeverConstant::Forever;
0026
0027 constexpr QDeadlineTimer() noexcept = default;
0028 constexpr explicit QDeadlineTimer(Qt::TimerType type_) noexcept
0029 : type(type_) {}
0030 constexpr QDeadlineTimer(ForeverConstant, Qt::TimerType type_ = Qt::CoarseTimer) noexcept
0031 : t1((std::numeric_limits<qint64>::max)()), type(type_) {}
0032 explicit QDeadlineTimer(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) noexcept;
0033
0034 void swap(QDeadlineTimer &other) noexcept
0035 { std::swap(t1, other.t1); std::swap(type, other.type); }
0036
0037 constexpr bool isForever() const noexcept
0038 { return t1 == (std::numeric_limits<qint64>::max)(); }
0039 bool hasExpired() const noexcept;
0040
0041 Qt::TimerType timerType() const noexcept
0042 { return Qt::TimerType(type & 0xff); }
0043 void setTimerType(Qt::TimerType type);
0044
0045 qint64 remainingTime() const noexcept;
0046 qint64 remainingTimeNSecs() const noexcept;
0047 void setRemainingTime(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) noexcept;
0048 void setPreciseRemainingTime(qint64 secs, qint64 nsecs = 0,
0049 Qt::TimerType type = Qt::CoarseTimer) noexcept;
0050
0051 qint64 deadline() const noexcept Q_DECL_PURE_FUNCTION;
0052 qint64 deadlineNSecs() const noexcept Q_DECL_PURE_FUNCTION;
0053 void setDeadline(qint64 msecs, Qt::TimerType timerType = Qt::CoarseTimer) noexcept;
0054 void setPreciseDeadline(qint64 secs, qint64 nsecs = 0,
0055 Qt::TimerType type = Qt::CoarseTimer) noexcept;
0056
0057 static QDeadlineTimer addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcept Q_DECL_PURE_FUNCTION;
0058 static QDeadlineTimer current(Qt::TimerType timerType = Qt::CoarseTimer) noexcept;
0059
0060 friend Q_CORE_EXPORT QDeadlineTimer operator+(QDeadlineTimer dt, qint64 msecs);
0061 friend QDeadlineTimer operator+(qint64 msecs, QDeadlineTimer dt)
0062 { return dt + msecs; }
0063 friend QDeadlineTimer operator-(QDeadlineTimer dt, qint64 msecs)
0064 { return dt + (-msecs); }
0065 friend qint64 operator-(QDeadlineTimer dt1, QDeadlineTimer dt2)
0066 { return (dt1.deadlineNSecs() - dt2.deadlineNSecs()) / (1000 * 1000); }
0067 QDeadlineTimer &operator+=(qint64 msecs)
0068 { *this = *this + msecs; return *this; }
0069 QDeadlineTimer &operator-=(qint64 msecs)
0070 { *this = *this + (-msecs); return *this; }
0071
0072 template <class Clock, class Duration = typename Clock::duration>
0073 QDeadlineTimer(std::chrono::time_point<Clock, Duration> deadline_,
0074 Qt::TimerType type_ = Qt::CoarseTimer) : t2(0)
0075 { setDeadline(deadline_, type_); }
0076 template <class Clock, class Duration = typename Clock::duration>
0077 QDeadlineTimer &operator=(std::chrono::time_point<Clock, Duration> deadline_)
0078 { setDeadline(deadline_); return *this; }
0079
0080 template <class Clock, class Duration = typename Clock::duration>
0081 void setDeadline(std::chrono::time_point<Clock, Duration> tp,
0082 Qt::TimerType type_ = Qt::CoarseTimer);
0083
0084 template <class Clock, class Duration = typename Clock::duration>
0085 std::chrono::time_point<Clock, Duration> deadline() const;
0086
0087 template <class Rep, class Period>
0088 QDeadlineTimer(std::chrono::duration<Rep, Period> remaining, Qt::TimerType type_ = Qt::CoarseTimer)
0089 : t2(0)
0090 { setRemainingTime(remaining, type_); }
0091
0092 template <class Rep, class Period>
0093 QDeadlineTimer &operator=(std::chrono::duration<Rep, Period> remaining)
0094 { setRemainingTime(remaining); return *this; }
0095
0096 template <class Rep, class Period>
0097 void setRemainingTime(std::chrono::duration<Rep, Period> remaining, Qt::TimerType type_ = Qt::CoarseTimer)
0098 {
0099 using namespace std::chrono;
0100 if (remaining == remaining.max())
0101 *this = QDeadlineTimer(Forever, type_);
0102 else
0103 setPreciseRemainingTime(0, ceil<nanoseconds>(remaining).count(), type_);
0104 }
0105
0106 std::chrono::nanoseconds remainingTimeAsDuration() const noexcept
0107 {
0108 if (isForever())
0109 return std::chrono::nanoseconds::max();
0110 qint64 nsecs = rawRemainingTimeNSecs();
0111 if (nsecs <= 0)
0112 return std::chrono::nanoseconds::zero();
0113 return std::chrono::nanoseconds(nsecs);
0114 }
0115
0116 template <class Rep, class Period>
0117 friend QDeadlineTimer operator+(QDeadlineTimer dt, std::chrono::duration<Rep, Period> value)
0118 { return QDeadlineTimer::addNSecs(dt, std::chrono::duration_cast<std::chrono::nanoseconds>(value).count()); }
0119 template <class Rep, class Period>
0120 friend QDeadlineTimer operator+(std::chrono::duration<Rep, Period> value, QDeadlineTimer dt)
0121 { return dt + value; }
0122 template <class Rep, class Period>
0123 friend QDeadlineTimer operator+=(QDeadlineTimer &dt, std::chrono::duration<Rep, Period> value)
0124 { return dt = dt + value; }
0125
0126 private:
0127 friend bool comparesEqual(const QDeadlineTimer &lhs,
0128 const QDeadlineTimer &rhs) noexcept
0129 {
0130 return lhs.t1 == rhs.t1;
0131 }
0132 friend Qt::strong_ordering compareThreeWay(const QDeadlineTimer &lhs,
0133 const QDeadlineTimer &rhs) noexcept
0134 {
0135 return Qt::compareThreeWay(lhs.t1, rhs.t1);
0136 }
0137 Q_DECLARE_STRONGLY_ORDERED(QDeadlineTimer)
0138
0139 qint64 t1 = 0;
0140 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
0141 unsigned t2 = 0;
0142 #endif
0143 unsigned type = Qt::CoarseTimer;
0144
0145 qint64 rawRemainingTimeNSecs() const noexcept;
0146 };
0147
0148 template<class Clock, class Duration>
0149 std::chrono::time_point<Clock, Duration> QDeadlineTimer::deadline() const
0150 {
0151 using namespace std::chrono;
0152 if constexpr (std::is_same_v<Clock, steady_clock>) {
0153 auto val = duration_cast<Duration>(nanoseconds(deadlineNSecs()));
0154 return time_point<Clock, Duration>(val);
0155 } else {
0156 auto val = nanoseconds(rawRemainingTimeNSecs()) + Clock::now();
0157 return time_point_cast<Duration>(val);
0158 }
0159 }
0160
0161 template<class Clock, class Duration>
0162 void QDeadlineTimer::setDeadline(std::chrono::time_point<Clock, Duration> tp, Qt::TimerType type_)
0163 {
0164 using namespace std::chrono;
0165 if (tp == tp.max()) {
0166 *this = Forever;
0167 type = type_;
0168 } else if constexpr (std::is_same_v<Clock, steady_clock>) {
0169 setPreciseDeadline(0,
0170 duration_cast<nanoseconds>(tp.time_since_epoch()).count(),
0171 type_);
0172 } else {
0173 setPreciseRemainingTime(0, duration_cast<nanoseconds>(tp - Clock::now()).count(), type_);
0174 }
0175 }
0176
0177 Q_DECLARE_SHARED(QDeadlineTimer)
0178
0179 QT_END_NAMESPACE
0180
0181 QT_DECL_METATYPE_EXTERN(QDeadlineTimer, Q_CORE_EXPORT)
0182
0183 #endif