LCOV - code coverage report
Current view: directory - objdir/dist/include/mozilla - TimeStamp.h (source / functions) Found Hit Coverage
Test: app.info Lines: 87 50 57.5 %
Date: 2012-06-02 Functions: 29 17 58.6 %

       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
       5                 :  *
       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/
      10                 :  *
      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
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla code.
      17                 :  *
      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.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *  Robert O'Callahan <robert@ocallahan.org>
      24                 :  *
      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.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #ifndef mozilla_TimeStamp_h
      40                 : #define mozilla_TimeStamp_h
      41                 : 
      42                 : #include "mozilla/Assertions.h"
      43                 : 
      44                 : #include "prinrval.h"
      45                 : #include "nsDebug.h"
      46                 : #include "prlong.h"
      47                 : 
      48                 : namespace mozilla {
      49                 : 
      50                 : class TimeStamp;
      51                 : 
      52                 : /**
      53                 :  * Instances of this class represent the length of an interval of time.
      54                 :  * Negative durations are allowed, meaning the end is before the start.
      55                 :  * 
      56                 :  * Internally the duration is stored as a PRInt64 in units of
      57                 :  * PR_TicksPerSecond() when building with NSPR interval timers, or a
      58                 :  * system-dependent unit when building with system clocks.  The
      59                 :  * system-dependent unit must be constant, otherwise the semantics of
      60                 :  * this class would be broken.
      61                 :  */
      62                 : class TimeDuration
      63                 : {
      64                 : public:
      65                 :   // The default duration is 0.
      66         1002727 :   TimeDuration() : mValue(0) {}
      67                 :   // Allow construction using '0' as the initial value, for readability,
      68                 :   // but no other numbers (so we don't have any implicit unit conversions).
      69                 :   struct _SomethingVeryRandomHere;
      70              21 :   TimeDuration(_SomethingVeryRandomHere* aZero) : mValue(0) {
      71              21 :     MOZ_ASSERT(!aZero, "Who's playing funny games here?");
      72              21 :   }
      73                 :   // Default copy-constructor and assignment are OK
      74                 : 
      75                 :   double ToSeconds() const;
      76                 :   // Return a duration value that includes digits of time we think to
      77                 :   // be significant.  This method should be used when displaying a
      78                 :   // time to humans.
      79                 :   double ToSecondsSigDigits() const;
      80          903298 :   double ToMilliseconds() const {
      81          903298 :     return ToSeconds() * 1000.0;
      82                 :   }
      83               0 :   double ToMicroseconds() const {
      84               0 :     return ToMilliseconds() * 1000.0;
      85                 :   }
      86                 : 
      87                 :   // Using a double here is safe enough; with 53 bits we can represent
      88                 :   // durations up to over 280,000 years exactly.  If the units of
      89                 :   // mValue do not allow us to represent durations of that length,
      90                 :   // long durations are clamped to the max/min representable value
      91                 :   // instead of overflowing.
      92               0 :   static inline TimeDuration FromSeconds(double aSeconds) {
      93               0 :     return FromMilliseconds(aSeconds * 1000.0);
      94                 :   }
      95                 :   static TimeDuration FromMilliseconds(double aMilliseconds);
      96                 :   static inline TimeDuration FromMicroseconds(double aMicroseconds) {
      97                 :     return FromMilliseconds(aMicroseconds / 1000.0);
      98                 :   }
      99                 : 
     100               0 :   TimeDuration operator+(const TimeDuration& aOther) const {
     101               0 :     return TimeDuration::FromTicks(mValue + aOther.mValue);
     102                 :   }
     103               0 :   TimeDuration operator-(const TimeDuration& aOther) const {
     104               0 :     return TimeDuration::FromTicks(mValue - aOther.mValue);
     105                 :   }
     106               4 :   TimeDuration& operator+=(const TimeDuration& aOther) {
     107               4 :     mValue += aOther.mValue;
     108               4 :     return *this;
     109                 :   }
     110                 :   TimeDuration& operator-=(const TimeDuration& aOther) {
     111                 :     mValue -= aOther.mValue;
     112                 :     return *this;
     113                 :   }
     114               0 :   double operator/(const TimeDuration& aOther) {
     115               0 :     return static_cast<double>(mValue) / aOther.mValue;
     116                 :   }
     117                 : 
     118            4241 :   bool operator<(const TimeDuration& aOther) const {
     119            4241 :     return mValue < aOther.mValue;
     120                 :   }
     121               0 :   bool operator<=(const TimeDuration& aOther) const {
     122               0 :     return mValue <= aOther.mValue;
     123                 :   }
     124               0 :   bool operator>=(const TimeDuration& aOther) const {
     125               0 :     return mValue >= aOther.mValue;
     126                 :   }
     127           27785 :   bool operator>(const TimeDuration& aOther) const {
     128           27785 :     return mValue > aOther.mValue;
     129                 :   }
     130                 : 
     131                 :   // Return a best guess at the system's current timing resolution,
     132                 :   // which might be variable.  TimeDurations below this order of
     133                 :   // magnitude are meaningless, and those at the same order of
     134                 :   // magnitude or just above are suspect.
     135                 :   static TimeDuration Resolution();
     136                 : 
     137                 :   // We could define additional operators here:
     138                 :   // -- convert to/from other time units
     139                 :   // -- scale duration by a float
     140                 :   // but let's do that on demand.
     141                 :   // Comparing durations for equality will only lead to bugs on
     142                 :   // platforms with high-resolution timers.
     143                 : 
     144                 : private:
     145                 :   friend class TimeStamp;
     146                 : 
     147          999820 :   static TimeDuration FromTicks(PRInt64 aTicks) {
     148          999820 :     TimeDuration t;
     149          999820 :     t.mValue = aTicks;
     150                 :     return t;
     151                 :   }
     152                 : 
     153           72098 :   static TimeDuration FromTicks(double aTicks) {
     154                 :     // NOTE: this MUST be a >= test, because PRInt64(double(LL_MAXINT))
     155                 :     // overflows and gives LL_MININT.
     156           72098 :     if (aTicks >= double(LL_MAXINT))
     157               0 :       return TimeDuration::FromTicks(LL_MAXINT);
     158                 : 
     159                 :     // This MUST be a <= test.
     160           72098 :     if (aTicks <= double(LL_MININT))
     161               0 :       return TimeDuration::FromTicks(LL_MININT);
     162                 : 
     163           72098 :     return TimeDuration::FromTicks(PRInt64(aTicks));
     164                 :   }
     165                 : 
     166                 :   // Duration in PRIntervalTime units
     167                 :   PRInt64 mValue;
     168                 : };
     169                 : 
     170                 : /**
     171                 :  * Instances of this class represent moments in time, or a special
     172                 :  * "null" moment. We do not use the non-monotonic system clock or
     173                 :  * local time, since they can be reset, causing apparent backward
     174                 :  * travel in time, which can confuse algorithms. Instead we measure
     175                 :  * elapsed time according to the system.  This time can never go
     176                 :  * backwards (i.e. it never wraps around, at least not in less than
     177                 :  * five million years of system elapsed time). It might not advance
     178                 :  * while the system is sleeping. If TimeStamp::SetNow() is not called
     179                 :  * at all for hours or days, we might not notice the passage of some
     180                 :  * of that time.
     181                 :  * 
     182                 :  * We deliberately do not expose a way to convert TimeStamps to some
     183                 :  * particular unit. All you can do is compute a difference between two
     184                 :  * TimeStamps to get a TimeDuration. You can also add a TimeDuration
     185                 :  * to a TimeStamp to get a new TimeStamp. You can't do something
     186                 :  * meaningless like add two TimeStamps.
     187                 :  *
     188                 :  * Internally this is implemented as either a wrapper around
     189                 :  *   - high-resolution, monotonic, system clocks if they exist on this
     190                 :  *     platform
     191                 :  *   - PRIntervalTime otherwise.  We detect wraparounds of
     192                 :  *     PRIntervalTime and work around them.
     193                 :  *
     194                 :  * This class is similar to C++11's time_point, however it is
     195                 :  * explicitly nullable and provides an IsNull() method. time_point
     196                 :  * is initialized to the clock's epoch and provides a
     197                 :  * time_since_epoch() method that functions similiarly. i.e.
     198                 :  * t.IsNull() is equivalent to t.time_since_epoch() == decltype(t)::duration::zero();
     199                 :  */
     200                 : class TimeStamp
     201                 : {
     202                 : public:
     203                 :   /**
     204                 :    * Initialize to the "null" moment
     205                 :    */
     206          139116 :   TimeStamp() : mValue(0) {}
     207                 :   // Default copy-constructor and assignment are OK
     208                 : 
     209                 :   /**
     210                 :    * Return true if this is the "null" moment
     211                 :    */
     212         2213351 :   bool IsNull() const { return mValue == 0; }
     213                 :   /**
     214                 :    * Return a timestamp reflecting the current elapsed system time. This
     215                 :    * is monotonically increasing (i.e., does not decrease) over the
     216                 :    * lifetime of this process' XPCOM session.
     217                 :    */
     218                 :   static TimeStamp Now();
     219                 :   /**
     220                 :    * Compute the difference between two timestamps. Both must be non-null.
     221                 :    */
     222          927723 :   TimeDuration operator-(const TimeStamp& aOther) const {
     223          927723 :     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
     224          927723 :     MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
     225                 :     PR_STATIC_ASSERT(-LL_MAXINT > LL_MININT);
     226          927723 :     PRInt64 ticks = PRInt64(mValue - aOther.mValue);
     227                 :     // Check for overflow.
     228          927723 :     if (mValue > aOther.mValue) {
     229          559590 :       if (ticks < 0) {
     230               0 :         ticks = LL_MAXINT;
     231                 :       }
     232                 :     } else {
     233          368133 :       if (ticks > 0) {
     234               0 :         ticks = LL_MININT;
     235                 :       }
     236                 :     }
     237          927723 :     return TimeDuration::FromTicks(ticks);
     238                 :   }
     239                 : 
     240           93304 :   TimeStamp operator+(const TimeDuration& aOther) const {
     241           93304 :     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
     242           93304 :     return TimeStamp(mValue + aOther.mValue);
     243                 :   }
     244               0 :   TimeStamp operator-(const TimeDuration& aOther) const {
     245               0 :     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
     246               0 :     return TimeStamp(mValue - aOther.mValue);
     247                 :   }
     248           26707 :   TimeStamp& operator+=(const TimeDuration& aOther) {
     249           26707 :     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
     250           26707 :     mValue += aOther.mValue;
     251           26707 :     return *this;
     252                 :   }
     253               1 :   TimeStamp& operator-=(const TimeDuration& aOther) {
     254               1 :     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
     255               1 :     mValue -= aOther.mValue;
     256               1 :     return *this;
     257                 :   }
     258                 : 
     259           74105 :   bool operator<(const TimeStamp& aOther) const {
     260           74105 :     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
     261           74105 :     MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
     262           74105 :     return mValue < aOther.mValue;
     263                 :   }
     264               0 :   bool operator<=(const TimeStamp& aOther) const {
     265               0 :     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
     266               0 :     MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
     267               0 :     return mValue <= aOther.mValue;
     268                 :   }
     269           28181 :   bool operator>=(const TimeStamp& aOther) const {
     270           28181 :     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
     271           28181 :     MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
     272           28181 :     return mValue >= aOther.mValue;
     273                 :   }
     274               0 :   bool operator>(const TimeStamp& aOther) const {
     275               0 :     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
     276               0 :     MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
     277               0 :     return mValue > aOther.mValue;
     278                 :   }
     279               0 :   bool operator==(const TimeStamp& aOther) const {
     280                 :     // Maybe it's ok to check == with null timestamps?
     281               0 :     MOZ_ASSERT(!IsNull() && "Cannot compute with a null value");
     282               0 :     MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
     283               0 :     return mValue == aOther.mValue;
     284                 :   }
     285               0 :   bool operator!=(const TimeStamp& aOther) const {
     286                 :     // Maybe it's ok to check != with null timestamps?
     287               0 :     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
     288               0 :     MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
     289               0 :     return mValue != aOther.mValue;
     290                 :   }
     291                 : 
     292                 :   // Comparing TimeStamps for equality should be discouraged. Adding
     293                 :   // two TimeStamps, or scaling TimeStamps, is nonsense and must never
     294                 :   // be allowed.
     295                 : 
     296                 :   static NS_HIDDEN_(nsresult) Startup();
     297                 :   static NS_HIDDEN_(void) Shutdown();
     298                 : 
     299                 : private:
     300         1965734 :   TimeStamp(PRUint64 aValue) : mValue(aValue) {}
     301                 : 
     302                 :   /**
     303                 :    * When built with PRIntervalTime, a value of 0 means this instance
     304                 :    * is "null". Otherwise, the low 32 bits represent a PRIntervalTime,
     305                 :    * and the high 32 bits represent a counter of the number of
     306                 :    * rollovers of PRIntervalTime that we've seen. This counter starts
     307                 :    * at 1 to avoid a real time colliding with the "null" value.
     308                 :    * 
     309                 :    * PR_INTERVAL_MAX is set at 100,000 ticks per second. So the minimum
     310                 :    * time to wrap around is about 2^64/100000 seconds, i.e. about
     311                 :    * 5,849,424 years.
     312                 :    *
     313                 :    * When using a system clock, a value is system dependent.
     314                 :    */
     315                 :   PRUint64 mValue;
     316                 : };
     317                 : 
     318                 : }
     319                 : 
     320                 : #endif /* mozilla_TimeStamp_h */

Generated by: LCOV version 1.7