Home | History | Annotate | Download | only in platform
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_PLATFORM_TIME_H_
     29 #define V8_PLATFORM_TIME_H_
     30 
     31 #include <ctime>
     32 #include <limits>
     33 
     34 #include "../allocation.h"
     35 
     36 // Forward declarations.
     37 extern "C" {
     38 struct _FILETIME;
     39 struct mach_timespec;
     40 struct timespec;
     41 struct timeval;
     42 }
     43 
     44 namespace v8 {
     45 namespace internal {
     46 
     47 class Time;
     48 class TimeTicks;
     49 
     50 // -----------------------------------------------------------------------------
     51 // TimeDelta
     52 //
     53 // This class represents a duration of time, internally represented in
     54 // microseonds.
     55 
     56 class TimeDelta V8_FINAL BASE_EMBEDDED {
     57  public:
     58   TimeDelta() : delta_(0) {}
     59 
     60   // Converts units of time to TimeDeltas.
     61   static TimeDelta FromDays(int days);
     62   static TimeDelta FromHours(int hours);
     63   static TimeDelta FromMinutes(int minutes);
     64   static TimeDelta FromSeconds(int64_t seconds);
     65   static TimeDelta FromMilliseconds(int64_t milliseconds);
     66   static TimeDelta FromMicroseconds(int64_t microseconds) {
     67     return TimeDelta(microseconds);
     68   }
     69   static TimeDelta FromNanoseconds(int64_t nanoseconds);
     70 
     71   // Returns the time delta in some unit. The F versions return a floating
     72   // point value, the "regular" versions return a rounded-down value.
     73   //
     74   // InMillisecondsRoundedUp() instead returns an integer that is rounded up
     75   // to the next full millisecond.
     76   int InDays() const;
     77   int InHours() const;
     78   int InMinutes() const;
     79   double InSecondsF() const;
     80   int64_t InSeconds() const;
     81   double InMillisecondsF() const;
     82   int64_t InMilliseconds() const;
     83   int64_t InMillisecondsRoundedUp() const;
     84   int64_t InMicroseconds() const { return delta_; }
     85   int64_t InNanoseconds() const;
     86 
     87   // Converts to/from Mach time specs.
     88   static TimeDelta FromMachTimespec(struct mach_timespec ts);
     89   struct mach_timespec ToMachTimespec() const;
     90 
     91   // Converts to/from POSIX time specs.
     92   static TimeDelta FromTimespec(struct timespec ts);
     93   struct timespec ToTimespec() const;
     94 
     95   TimeDelta& operator=(const TimeDelta& other) {
     96     delta_ = other.delta_;
     97     return *this;
     98   }
     99 
    100   // Computations with other deltas.
    101   TimeDelta operator+(const TimeDelta& other) const {
    102     return TimeDelta(delta_ + other.delta_);
    103   }
    104   TimeDelta operator-(const TimeDelta& other) const {
    105     return TimeDelta(delta_ - other.delta_);
    106   }
    107 
    108   TimeDelta& operator+=(const TimeDelta& other) {
    109     delta_ += other.delta_;
    110     return *this;
    111   }
    112   TimeDelta& operator-=(const TimeDelta& other) {
    113     delta_ -= other.delta_;
    114     return *this;
    115   }
    116   TimeDelta operator-() const {
    117     return TimeDelta(-delta_);
    118   }
    119 
    120   double TimesOf(const TimeDelta& other) const {
    121     return static_cast<double>(delta_) / static_cast<double>(other.delta_);
    122   }
    123   double PercentOf(const TimeDelta& other) const {
    124     return TimesOf(other) * 100.0;
    125   }
    126 
    127   // Computations with ints, note that we only allow multiplicative operations
    128   // with ints, and additive operations with other deltas.
    129   TimeDelta operator*(int64_t a) const {
    130     return TimeDelta(delta_ * a);
    131   }
    132   TimeDelta operator/(int64_t a) const {
    133     return TimeDelta(delta_ / a);
    134   }
    135   TimeDelta& operator*=(int64_t a) {
    136     delta_ *= a;
    137     return *this;
    138   }
    139   TimeDelta& operator/=(int64_t a) {
    140     delta_ /= a;
    141     return *this;
    142   }
    143   int64_t operator/(const TimeDelta& other) const {
    144     return delta_ / other.delta_;
    145   }
    146 
    147   // Comparison operators.
    148   bool operator==(const TimeDelta& other) const {
    149     return delta_ == other.delta_;
    150   }
    151   bool operator!=(const TimeDelta& other) const {
    152     return delta_ != other.delta_;
    153   }
    154   bool operator<(const TimeDelta& other) const {
    155     return delta_ < other.delta_;
    156   }
    157   bool operator<=(const TimeDelta& other) const {
    158     return delta_ <= other.delta_;
    159   }
    160   bool operator>(const TimeDelta& other) const {
    161     return delta_ > other.delta_;
    162   }
    163   bool operator>=(const TimeDelta& other) const {
    164     return delta_ >= other.delta_;
    165   }
    166 
    167  private:
    168   // Constructs a delta given the duration in microseconds. This is private
    169   // to avoid confusion by callers with an integer constructor. Use
    170   // FromSeconds, FromMilliseconds, etc. instead.
    171   explicit TimeDelta(int64_t delta) : delta_(delta) {}
    172 
    173   // Delta in microseconds.
    174   int64_t delta_;
    175 };
    176 
    177 
    178 // -----------------------------------------------------------------------------
    179 // Time
    180 //
    181 // This class represents an absolute point in time, internally represented as
    182 // microseconds (s/1,000,000) since 00:00:00 UTC, January 1, 1970.
    183 
    184 class Time V8_FINAL BASE_EMBEDDED {
    185  public:
    186   static const int64_t kMillisecondsPerSecond = 1000;
    187   static const int64_t kMicrosecondsPerMillisecond = 1000;
    188   static const int64_t kMicrosecondsPerSecond = kMicrosecondsPerMillisecond *
    189                                                 kMillisecondsPerSecond;
    190   static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60;
    191   static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60;
    192   static const int64_t kMicrosecondsPerDay = kMicrosecondsPerHour * 24;
    193   static const int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7;
    194   static const int64_t kNanosecondsPerMicrosecond = 1000;
    195   static const int64_t kNanosecondsPerSecond = kNanosecondsPerMicrosecond *
    196                                                kMicrosecondsPerSecond;
    197 
    198   // Contains the NULL time. Use Time::Now() to get the current time.
    199   Time() : us_(0) {}
    200 
    201   // Returns true if the time object has not been initialized.
    202   bool IsNull() const { return us_ == 0; }
    203 
    204   // Returns true if the time object is the maximum time.
    205   bool IsMax() const { return us_ == std::numeric_limits<int64_t>::max(); }
    206 
    207   // Returns the current time. Watch out, the system might adjust its clock
    208   // in which case time will actually go backwards. We don't guarantee that
    209   // times are increasing, or that two calls to Now() won't be the same.
    210   static Time Now();
    211 
    212   // Returns the current time. Same as Now() except that this function always
    213   // uses system time so that there are no discrepancies between the returned
    214   // time and system time even on virtual environments including our test bot.
    215   // For timing sensitive unittests, this function should be used.
    216   static Time NowFromSystemTime();
    217 
    218   // Returns the time for epoch in Unix-like system (Jan 1, 1970).
    219   static Time UnixEpoch() { return Time(0); }
    220 
    221   // Returns the maximum time, which should be greater than any reasonable time
    222   // with which we might compare it.
    223   static Time Max() { return Time(std::numeric_limits<int64_t>::max()); }
    224 
    225   // Converts to/from internal values. The meaning of the "internal value" is
    226   // completely up to the implementation, so it should be treated as opaque.
    227   static Time FromInternalValue(int64_t value) {
    228     return Time(value);
    229   }
    230   int64_t ToInternalValue() const {
    231     return us_;
    232   }
    233 
    234   // Converts to/from POSIX time specs.
    235   static Time FromTimespec(struct timespec ts);
    236   struct timespec ToTimespec() const;
    237 
    238   // Converts to/from POSIX time values.
    239   static Time FromTimeval(struct timeval tv);
    240   struct timeval ToTimeval() const;
    241 
    242   // Converts to/from Windows file times.
    243   static Time FromFiletime(struct _FILETIME ft);
    244   struct _FILETIME ToFiletime() const;
    245 
    246   // Converts to/from the Javascript convention for times, a number of
    247   // milliseconds since the epoch:
    248   static Time FromJsTime(double ms_since_epoch);
    249   double ToJsTime() const;
    250 
    251   Time& operator=(const Time& other) {
    252     us_ = other.us_;
    253     return *this;
    254   }
    255 
    256   // Compute the difference between two times.
    257   TimeDelta operator-(const Time& other) const {
    258     return TimeDelta::FromMicroseconds(us_ - other.us_);
    259   }
    260 
    261   // Modify by some time delta.
    262   Time& operator+=(const TimeDelta& delta) {
    263     us_ += delta.InMicroseconds();
    264     return *this;
    265   }
    266   Time& operator-=(const TimeDelta& delta) {
    267     us_ -= delta.InMicroseconds();
    268     return *this;
    269   }
    270 
    271   // Return a new time modified by some delta.
    272   Time operator+(const TimeDelta& delta) const {
    273     return Time(us_ + delta.InMicroseconds());
    274   }
    275   Time operator-(const TimeDelta& delta) const {
    276     return Time(us_ - delta.InMicroseconds());
    277   }
    278 
    279   // Comparison operators
    280   bool operator==(const Time& other) const {
    281     return us_ == other.us_;
    282   }
    283   bool operator!=(const Time& other) const {
    284     return us_ != other.us_;
    285   }
    286   bool operator<(const Time& other) const {
    287     return us_ < other.us_;
    288   }
    289   bool operator<=(const Time& other) const {
    290     return us_ <= other.us_;
    291   }
    292   bool operator>(const Time& other) const {
    293     return us_ > other.us_;
    294   }
    295   bool operator>=(const Time& other) const {
    296     return us_ >= other.us_;
    297   }
    298 
    299  private:
    300   explicit Time(int64_t us) : us_(us) {}
    301 
    302   // Time in microseconds in UTC.
    303   int64_t us_;
    304 };
    305 
    306 inline Time operator+(const TimeDelta& delta, const Time& time) {
    307   return time + delta;
    308 }
    309 
    310 
    311 // -----------------------------------------------------------------------------
    312 // TimeTicks
    313 //
    314 // This class represents an abstract time that is most of the time incrementing
    315 // for use in measuring time durations. It is internally represented in
    316 // microseconds.  It can not be converted to a human-readable time, but is
    317 // guaranteed not to decrease (if the user changes the computer clock,
    318 // Time::Now() may actually decrease or jump).  But note that TimeTicks may
    319 // "stand still", for example if the computer suspended.
    320 
    321 class TimeTicks V8_FINAL BASE_EMBEDDED {
    322  public:
    323   TimeTicks() : ticks_(0) {}
    324 
    325   // Platform-dependent tick count representing "right now."
    326   // The resolution of this clock is ~1-15ms.  Resolution varies depending
    327   // on hardware/operating system configuration.
    328   // This method never returns a null TimeTicks.
    329   static TimeTicks Now();
    330 
    331   // Returns a platform-dependent high-resolution tick count. Implementation
    332   // is hardware dependent and may or may not return sub-millisecond
    333   // resolution.  THIS CALL IS GENERALLY MUCH MORE EXPENSIVE THAN Now() AND
    334   // SHOULD ONLY BE USED WHEN IT IS REALLY NEEDED.
    335   // This method never returns a null TimeTicks.
    336   static TimeTicks HighResolutionNow();
    337 
    338   // Returns true if the high-resolution clock is working on this system.
    339   static bool IsHighResolutionClockWorking();
    340 
    341   // Returns true if this object has not been initialized.
    342   bool IsNull() const { return ticks_ == 0; }
    343 
    344   // Converts to/from internal values. The meaning of the "internal value" is
    345   // completely up to the implementation, so it should be treated as opaque.
    346   static TimeTicks FromInternalValue(int64_t value) {
    347     return TimeTicks(value);
    348   }
    349   int64_t ToInternalValue() const {
    350     return ticks_;
    351   }
    352 
    353   TimeTicks& operator=(const TimeTicks other) {
    354     ticks_ = other.ticks_;
    355     return *this;
    356   }
    357 
    358   // Compute the difference between two times.
    359   TimeDelta operator-(const TimeTicks other) const {
    360     return TimeDelta::FromMicroseconds(ticks_ - other.ticks_);
    361   }
    362 
    363   // Modify by some time delta.
    364   TimeTicks& operator+=(const TimeDelta& delta) {
    365     ticks_ += delta.InMicroseconds();
    366     return *this;
    367   }
    368   TimeTicks& operator-=(const TimeDelta& delta) {
    369     ticks_ -= delta.InMicroseconds();
    370     return *this;
    371   }
    372 
    373   // Return a new TimeTicks modified by some delta.
    374   TimeTicks operator+(const TimeDelta& delta) const {
    375     return TimeTicks(ticks_ + delta.InMicroseconds());
    376   }
    377   TimeTicks operator-(const TimeDelta& delta) const {
    378     return TimeTicks(ticks_ - delta.InMicroseconds());
    379   }
    380 
    381   // Comparison operators
    382   bool operator==(const TimeTicks& other) const {
    383     return ticks_ == other.ticks_;
    384   }
    385   bool operator!=(const TimeTicks& other) const {
    386     return ticks_ != other.ticks_;
    387   }
    388   bool operator<(const TimeTicks& other) const {
    389     return ticks_ < other.ticks_;
    390   }
    391   bool operator<=(const TimeTicks& other) const {
    392     return ticks_ <= other.ticks_;
    393   }
    394   bool operator>(const TimeTicks& other) const {
    395     return ticks_ > other.ticks_;
    396   }
    397   bool operator>=(const TimeTicks& other) const {
    398     return ticks_ >= other.ticks_;
    399   }
    400 
    401  private:
    402   // Please use Now() to create a new object. This is for internal use
    403   // and testing. Ticks is in microseconds.
    404   explicit TimeTicks(int64_t ticks) : ticks_(ticks) {}
    405 
    406   // Tick count in microseconds.
    407   int64_t ticks_;
    408 };
    409 
    410 inline TimeTicks operator+(const TimeDelta& delta, const TimeTicks& ticks) {
    411   return ticks + delta;
    412 }
    413 
    414 } }  // namespace v8::internal
    415 
    416 #endif  // V8_PLATFORM_TIME_H_
    417