1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is Mozilla code.
18 * The Initial Developer of the Original Code is the Mozilla Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2009
20 * the Initial Developer. All Rights Reserved.
23 * Robert O'Callahan <robert@ocallahan.org>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #ifndef mozilla_TimeStamp_h
40 #define mozilla_TimeStamp_h
50 * Instances of this class represent the length of an interval of time.
51 * Negative durations are allowed, meaning the end is before the start.
53 * Internally the duration is stored as a PRInt64 in units of
54 * PR_TicksPerSecond() when building with NSPR interval timers, or a
55 * system-dependent unit when building with system clocks. The
56 * system-dependent unit must be constant, otherwise the semantics of
57 * this class would be broken.
59 class NS_COM TimeDuration
62 // The default duration is 0.
63 TimeDuration() : mValue(0) {}
64 // Allow construction using '0' as the initial value, for readability,
65 // but no other numbers (so we don't have any implicit unit conversions).
66 struct _SomethingVeryRandomHere
;
67 TimeDuration(_SomethingVeryRandomHere
* aZero
) : mValue(0) {
68 NS_ASSERTION(!aZero
, "Who's playing funny games here?");
70 // Default copy-constructor and assignment are OK
72 double ToSeconds() const;
73 // Return a duration value that includes digits of time we think to
74 // be significant. This method should be used when displaying a
76 double ToSecondsSigDigits() const;
78 static TimeDuration
FromSeconds(PRInt32 aSeconds
);
79 static TimeDuration
FromMilliseconds(PRInt32 aMilliseconds
);
81 TimeDuration
operator+(const TimeDuration
& aOther
) const {
82 return TimeDuration::FromTicks(mValue
+ aOther
.mValue
);
84 TimeDuration
operator-(const TimeDuration
& aOther
) const {
85 return TimeDuration::FromTicks(mValue
- aOther
.mValue
);
87 TimeDuration
& operator+=(const TimeDuration
& aOther
) {
88 mValue
+= aOther
.mValue
;
91 TimeDuration
& operator-=(const TimeDuration
& aOther
) {
92 mValue
-= aOther
.mValue
;
96 PRBool
operator<(const TimeDuration
& aOther
) const {
97 return mValue
< aOther
.mValue
;
99 PRBool
operator<=(const TimeDuration
& aOther
) const {
100 return mValue
<= aOther
.mValue
;
102 PRBool
operator>=(const TimeDuration
& aOther
) const {
103 return mValue
>= aOther
.mValue
;
105 PRBool
operator>(const TimeDuration
& aOther
) const {
106 return mValue
> aOther
.mValue
;
109 // Return a best guess at the system's current timing resolution,
110 // which might be variable. TimeDurations below this order of
111 // magnitude are meaningless, and those at the same order of
112 // magnitude or just above are suspect.
113 static TimeDuration
Resolution();
115 // We could define additional operators here:
116 // -- convert to/from other time units
117 // -- scale duration by a float
118 // but let's do that on demand.
119 // Comparing durations for equality will only lead to bugs on
120 // platforms with high-resolution timers.
123 friend class TimeStamp
;
125 static TimeDuration
FromTicks(PRInt64 aTicks
) {
131 // Duration in PRIntervalTime units
136 * Instances of this class represent moments in time, or a special
137 * "null" moment. We do not use the non-monotonic system clock or
138 * local time, since they can be reset, causing apparent backward
139 * travel in time, which can confuse algorithms. Instead we measure
140 * elapsed time according to the system. This time can never go
141 * backwards (i.e. it never wraps around, at least not in less than
142 * five million years of system elapsed time). It might not advance
143 * while the system is sleeping. If TimeStamp::SetNow() is not called
144 * at all for hours or days, we might not notice the passage of some
147 * We deliberately do not expose a way to convert TimeStamps to some
148 * particular unit. All you can do is compute a difference between two
149 * TimeStamps to get a TimeDuration. You can also add a TimeDuration
150 * to a TimeStamp to get a new TimeStamp. You can't do something
151 * meaningless like add two TimeStamps.
153 * Internally this is implemented as either a wrapper around
154 * - high-resolution, monotonic, system clocks if they exist on this
156 * - PRIntervalTime otherwise. We detect wraparounds of
157 * PRIntervalTime and work around them.
159 class NS_COM TimeStamp
163 * Initialize to the "null" moment
165 TimeStamp() : mValue(0) {}
166 // Default copy-constructor and assignment are OK
169 * Return true if this is the "null" moment
171 PRBool
IsNull() const { return mValue
== 0; }
173 * Return a timestamp reflecting the current elapsed system time. This
174 * is monotonically increasing (i.e., does not decrease) over the
175 * lifetime of this process' XPCOM session.
177 static TimeStamp
Now();
179 * Compute the difference between two timestamps. Both must be non-null.
181 TimeDuration
operator-(const TimeStamp
& aOther
) const {
182 NS_ASSERTION(!IsNull(), "Cannot compute with a null value");
183 NS_ASSERTION(!aOther
.IsNull(), "Cannot compute with aOther null value");
184 return TimeDuration::FromTicks(mValue
- aOther
.mValue
);
187 TimeStamp
operator+(const TimeDuration
& aOther
) const {
188 NS_ASSERTION(!IsNull(), "Cannot compute with a null value");
189 return TimeStamp(mValue
+ aOther
.mValue
);
191 TimeStamp
operator-(const TimeDuration
& aOther
) const {
192 NS_ASSERTION(!IsNull(), "Cannot compute with a null value");
193 return TimeStamp(mValue
- aOther
.mValue
);
195 TimeStamp
& operator+=(const TimeDuration
& aOther
) {
196 NS_ASSERTION(!IsNull(), "Cannot compute with a null value");
197 mValue
+= aOther
.mValue
;
200 TimeStamp
& operator-=(const TimeDuration
& aOther
) {
201 NS_ASSERTION(!IsNull(), "Cannot compute with a null value");
202 mValue
-= aOther
.mValue
;
206 PRBool
operator<(const TimeStamp
& aOther
) const {
207 NS_ASSERTION(!IsNull(), "Cannot compute with a null value");
208 NS_ASSERTION(!aOther
.IsNull(), "Cannot compute with aOther null value");
209 return mValue
< aOther
.mValue
;
211 PRBool
operator<=(const TimeStamp
& aOther
) const {
212 NS_ASSERTION(!IsNull(), "Cannot compute with a null value");
213 NS_ASSERTION(!aOther
.IsNull(), "Cannot compute with aOther null value");
214 return mValue
<= aOther
.mValue
;
216 PRBool
operator>=(const TimeStamp
& aOther
) const {
217 NS_ASSERTION(!IsNull(), "Cannot compute with a null value");
218 NS_ASSERTION(!aOther
.IsNull(), "Cannot compute with aOther null value");
219 return mValue
>= aOther
.mValue
;
221 PRBool
operator>(const TimeStamp
& aOther
) const {
222 NS_ASSERTION(!IsNull(), "Cannot compute with a null value");
223 NS_ASSERTION(!aOther
.IsNull(), "Cannot compute with aOther null value");
224 return mValue
> aOther
.mValue
;
226 PRBool
operator==(const TimeStamp
& aOther
) const {
227 // Maybe it's ok to check == with null timestamps?
228 NS_ASSERTION(!IsNull(), "Cannot compute with a null value");
229 NS_ASSERTION(!aOther
.IsNull(), "Cannot compute with aOther null value");
230 return mValue
== aOther
.mValue
;
232 PRBool
operator!=(const TimeStamp
& aOther
) const {
233 // Maybe it's ok to check != with null timestamps?
234 NS_ASSERTION(!IsNull(), "Cannot compute with a null value");
235 NS_ASSERTION(!aOther
.IsNull(), "Cannot compute with aOther null value");
236 return mValue
!= aOther
.mValue
;
239 // Comparing TimeStamps for equality should be discouraged. Adding
240 // two TimeStamps, or scaling TimeStamps, is nonsense and must never
243 static NS_HIDDEN_(nsresult
) Startup();
244 static NS_HIDDEN_(void) Shutdown();
247 TimeStamp(PRUint64 aValue
) : mValue(aValue
) {}
250 * When built with PRIntervalTime, a value of 0 means this instance
251 * is "null". Otherwise, the low 32 bits represent a PRIntervalTime,
252 * and the high 32 bits represent a counter of the number of
253 * rollovers of PRIntervalTime that we've seen. This counter starts
254 * at 1 to avoid a real time colliding with the "null" value.
256 * PR_INTERVAL_MAX is set at 100,000 ticks per second. So the minimum
257 * time to wrap around is about 2^64/100000 seconds, i.e. about
260 * When using a system clock, a value is system dependent.
267 #endif /* mozilla_TimeStamp_h */