[WTF] Add Markable<T, Traits>
[WebKit-https.git] / Source / WTF / wtf / MonotonicTime.h
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef WTF_MonotonicTime_h
27 #define WTF_MonotonicTime_h
28
29 #include <wtf/ClockType.h>
30 #include <wtf/Seconds.h>
31
32 namespace WTF {
33
34 class WallTime;
35 class PrintStream;
36
37 // The current time according to a monotonic clock. Monotonic clocks don't go backwards and
38 // possibly don't count downtime. This uses floating point internally so that you can reason about
39 // infinity and other things that arise in math. It's acceptable to use this to wrap NaN times,
40 // negative times, and infinite times, so long as they are all relative to the same clock.
41 class MonotonicTime {
42 public:
43     static const ClockType clockType = ClockType::Monotonic;
44     
45     // This is the epoch. So, x.secondsSinceEpoch() should be the same as x - MonotonicTime().
46     constexpr MonotonicTime() { }
47     
48     // Call this if you know for sure that the double represents monotonic time according to the
49     // same time source as MonotonicTime. It must be in seconds.
50     static constexpr MonotonicTime fromRawSeconds(double value)
51     {
52         return MonotonicTime(value);
53     }
54     
55     WTF_EXPORT_PRIVATE static MonotonicTime now();
56     
57     static constexpr MonotonicTime infinity() { return fromRawSeconds(std::numeric_limits<double>::infinity()); }
58     static constexpr MonotonicTime nan() { return fromRawSeconds(std::numeric_limits<double>::quiet_NaN()); }
59
60     constexpr Seconds secondsSinceEpoch() const { return Seconds(m_value); }
61     
62     MonotonicTime approximateMonotonicTime() const { return *this; }
63     WTF_EXPORT_PRIVATE WallTime approximateWallTime() const;
64     
65     explicit constexpr operator bool() const { return !!m_value; }
66     
67     constexpr MonotonicTime operator+(Seconds other) const
68     {
69         return fromRawSeconds(m_value + other.value());
70     }
71     
72     constexpr MonotonicTime operator-(Seconds other) const
73     {
74         return fromRawSeconds(m_value - other.value());
75     }
76
77     Seconds operator%(Seconds other) const
78     {
79         return Seconds { fmod(m_value, other.value()) };
80     }
81     
82     // Time is a scalar and scalars can be negated as this could arise from algebraic
83     // transformations. So, we allow it.
84     constexpr MonotonicTime operator-() const
85     {
86         return fromRawSeconds(-m_value);
87     }
88     
89     MonotonicTime operator+=(Seconds other)
90     {
91         return *this = *this + other;
92     }
93     
94     MonotonicTime operator-=(Seconds other)
95     {
96         return *this = *this - other;
97     }
98     
99     constexpr Seconds operator-(MonotonicTime other) const
100     {
101         return Seconds(m_value - other.m_value);
102     }
103     
104     constexpr bool operator==(MonotonicTime other) const
105     {
106         return m_value == other.m_value;
107     }
108     
109     constexpr bool operator!=(MonotonicTime other) const
110     {
111         return m_value != other.m_value;
112     }
113     
114     constexpr bool operator<(MonotonicTime other) const
115     {
116         return m_value < other.m_value;
117     }
118     
119     constexpr bool operator>(MonotonicTime other) const
120     {
121         return m_value > other.m_value;
122     }
123     
124     constexpr bool operator<=(MonotonicTime other) const
125     {
126         return m_value <= other.m_value;
127     }
128     
129     constexpr bool operator>=(MonotonicTime other) const
130     {
131         return m_value >= other.m_value;
132     }
133     
134     WTF_EXPORT_PRIVATE void dump(PrintStream&) const;
135
136     MonotonicTime isolatedCopy() const
137     {
138         return *this;
139     }
140
141     template<class Encoder>
142     void encode(Encoder& encoder) const
143     {
144         encoder << m_value;
145     }
146
147     template<class Decoder>
148     static std::optional<MonotonicTime> decode(Decoder& decoder)
149     {
150         std::optional<double> time;
151         decoder >> time;
152         if (!time)
153             return std::nullopt;
154         return MonotonicTime::fromRawSeconds(*time);
155     }
156
157     template<class Decoder>
158     static bool decode(Decoder& decoder, MonotonicTime& time)
159     {
160         double value;
161         if (!decoder.decode(value))
162             return false;
163
164         time = MonotonicTime::fromRawSeconds(value);
165         return true;
166     }
167
168     struct MarkableTraits;
169
170 private:
171     constexpr MonotonicTime(double rawValue)
172         : m_value(rawValue)
173     {
174     }
175
176     double m_value { 0 };
177 };
178
179 struct MonotonicTime::MarkableTraits {
180     static bool isEmptyValue(MonotonicTime time)
181     {
182         return std::isnan(time.m_value);
183     }
184
185     static constexpr MonotonicTime emptyValue()
186     {
187         return MonotonicTime::nan();
188     }
189 };
190
191 } // namespace WTF
192
193 namespace std {
194
195 inline bool isnan(WTF::MonotonicTime time)
196 {
197     return std::isnan(time.secondsSinceEpoch().value());
198 }
199
200 inline bool isinf(WTF::MonotonicTime time)
201 {
202     return std::isinf(time.secondsSinceEpoch().value());
203 }
204
205 inline bool isfinite(WTF::MonotonicTime time)
206 {
207     return std::isfinite(time.secondsSinceEpoch().value());
208 }
209
210 } // namespace std
211
212 using WTF::MonotonicTime;
213
214 #endif // WTF_MonotonicTime_h