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