1218885Sdim//===-- TimeValue.h - Declare OS TimeValue Concept --------------*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This header file declares the operating system TimeValue concept. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14249423Sdim#ifndef LLVM_SUPPORT_TIMEVALUE_H 15249423Sdim#define LLVM_SUPPORT_TIMEVALUE_H 16249423Sdim 17218885Sdim#include "llvm/Support/DataTypes.h" 18218885Sdim#include <string> 19218885Sdim 20218885Sdimnamespace llvm { 21218885Sdimnamespace sys { 22218885Sdim /// This class is used where a precise fixed point in time is required. The 23218885Sdim /// range of TimeValue spans many hundreds of billions of years both past and 24218885Sdim /// present. The precision of TimeValue is to the nanosecond. However, the 25218885Sdim /// actual precision of its values will be determined by the resolution of 26218885Sdim /// the system clock. The TimeValue class is used in conjunction with several 27218885Sdim /// other lib/System interfaces to specify the time at which a call should 28218885Sdim /// timeout, etc. 29218885Sdim /// @since 1.4 30218885Sdim /// @brief Provides an abstraction for a fixed point in time. 31218885Sdim class TimeValue { 32218885Sdim 33218885Sdim /// @name Constants 34218885Sdim /// @{ 35218885Sdim public: 36218885Sdim 37218885Sdim /// A constant TimeValue representing the smallest time 38221345Sdim /// value permissible by the class. MinTime is some point 39218885Sdim /// in the distant past, about 300 billion years BCE. 40218885Sdim /// @brief The smallest possible time value. 41218885Sdim static const TimeValue MinTime; 42218885Sdim 43218885Sdim /// A constant TimeValue representing the largest time 44221345Sdim /// value permissible by the class. MaxTime is some point 45218885Sdim /// in the distant future, about 300 billion years AD. 46218885Sdim /// @brief The largest possible time value. 47218885Sdim static const TimeValue MaxTime; 48218885Sdim 49218885Sdim /// A constant TimeValue representing the base time, 50218885Sdim /// or zero time of 00:00:00 (midnight) January 1st, 2000. 51218885Sdim /// @brief 00:00:00 Jan 1, 2000 UTC. 52218885Sdim static const TimeValue ZeroTime; 53218885Sdim 54218885Sdim /// A constant TimeValue for the Posix base time which is 55218885Sdim /// 00:00:00 (midnight) January 1st, 1970. 56218885Sdim /// @brief 00:00:00 Jan 1, 1970 UTC. 57218885Sdim static const TimeValue PosixZeroTime; 58218885Sdim 59218885Sdim /// A constant TimeValue for the Win32 base time which is 60218885Sdim /// 00:00:00 (midnight) January 1st, 1601. 61218885Sdim /// @brief 00:00:00 Jan 1, 1601 UTC. 62218885Sdim static const TimeValue Win32ZeroTime; 63218885Sdim 64218885Sdim /// @} 65218885Sdim /// @name Types 66218885Sdim /// @{ 67218885Sdim public: 68218885Sdim typedef int64_t SecondsType; ///< Type used for representing seconds. 69218885Sdim typedef int32_t NanoSecondsType;///< Type used for representing nanoseconds. 70218885Sdim 71218885Sdim enum TimeConversions { 72218885Sdim NANOSECONDS_PER_SECOND = 1000000000, ///< One Billion 73218885Sdim MICROSECONDS_PER_SECOND = 1000000, ///< One Million 74218885Sdim MILLISECONDS_PER_SECOND = 1000, ///< One Thousand 75218885Sdim NANOSECONDS_PER_MICROSECOND = 1000, ///< One Thousand 76218885Sdim NANOSECONDS_PER_MILLISECOND = 1000000,///< One Million 77218885Sdim NANOSECONDS_PER_POSIX_TICK = 100, ///< Posix tick is 100 Hz (10ms) 78218885Sdim NANOSECONDS_PER_WIN32_TICK = 100 ///< Win32 tick is 100 Hz (10ms) 79218885Sdim }; 80218885Sdim 81218885Sdim /// @} 82218885Sdim /// @name Constructors 83218885Sdim /// @{ 84218885Sdim public: 85249423Sdim /// \brief Default construct a time value, initializing to ZeroTime. 86249423Sdim TimeValue() : seconds_(0), nanos_(0) {} 87249423Sdim 88218885Sdim /// Caller provides the exact value in seconds and nanoseconds. The 89218885Sdim /// \p nanos argument defaults to zero for convenience. 90218885Sdim /// @brief Explicit constructor 91218885Sdim explicit TimeValue (SecondsType seconds, NanoSecondsType nanos = 0) 92218885Sdim : seconds_( seconds ), nanos_( nanos ) { this->normalize(); } 93218885Sdim 94218885Sdim /// Caller provides the exact value as a double in seconds with the 95218885Sdim /// fractional part representing nanoseconds. 96218885Sdim /// @brief Double Constructor. 97218885Sdim explicit TimeValue( double new_time ) 98218885Sdim : seconds_( 0 ) , nanos_ ( 0 ) { 99218885Sdim SecondsType integer_part = static_cast<SecondsType>( new_time ); 100218885Sdim seconds_ = integer_part; 101218885Sdim nanos_ = static_cast<NanoSecondsType>( (new_time - 102218885Sdim static_cast<double>(integer_part)) * NANOSECONDS_PER_SECOND ); 103218885Sdim this->normalize(); 104218885Sdim } 105218885Sdim 106218885Sdim /// This is a static constructor that returns a TimeValue that represents 107218885Sdim /// the current time. 108218885Sdim /// @brief Creates a TimeValue with the current time (UTC). 109218885Sdim static TimeValue now(); 110218885Sdim 111218885Sdim /// @} 112218885Sdim /// @name Operators 113218885Sdim /// @{ 114218885Sdim public: 115218885Sdim /// Add \p that to \p this. 116218885Sdim /// @returns this 117218885Sdim /// @brief Incrementing assignment operator. 118218885Sdim TimeValue& operator += (const TimeValue& that ) { 119218885Sdim this->seconds_ += that.seconds_ ; 120218885Sdim this->nanos_ += that.nanos_ ; 121218885Sdim this->normalize(); 122218885Sdim return *this; 123218885Sdim } 124218885Sdim 125218885Sdim /// Subtract \p that from \p this. 126218885Sdim /// @returns this 127218885Sdim /// @brief Decrementing assignment operator. 128218885Sdim TimeValue& operator -= (const TimeValue &that ) { 129218885Sdim this->seconds_ -= that.seconds_ ; 130218885Sdim this->nanos_ -= that.nanos_ ; 131218885Sdim this->normalize(); 132218885Sdim return *this; 133218885Sdim } 134218885Sdim 135218885Sdim /// Determine if \p this is less than \p that. 136218885Sdim /// @returns True iff *this < that. 137218885Sdim /// @brief True if this < that. 138218885Sdim int operator < (const TimeValue &that) const { return that > *this; } 139218885Sdim 140218885Sdim /// Determine if \p this is greather than \p that. 141218885Sdim /// @returns True iff *this > that. 142218885Sdim /// @brief True if this > that. 143218885Sdim int operator > (const TimeValue &that) const { 144218885Sdim if ( this->seconds_ > that.seconds_ ) { 145218885Sdim return 1; 146218885Sdim } else if ( this->seconds_ == that.seconds_ ) { 147218885Sdim if ( this->nanos_ > that.nanos_ ) return 1; 148218885Sdim } 149218885Sdim return 0; 150218885Sdim } 151218885Sdim 152218885Sdim /// Determine if \p this is less than or equal to \p that. 153218885Sdim /// @returns True iff *this <= that. 154218885Sdim /// @brief True if this <= that. 155218885Sdim int operator <= (const TimeValue &that) const { return that >= *this; } 156218885Sdim 157218885Sdim /// Determine if \p this is greater than or equal to \p that. 158218885Sdim /// @returns True iff *this >= that. 159218885Sdim int operator >= (const TimeValue &that) const { 160218885Sdim if ( this->seconds_ > that.seconds_ ) { 161218885Sdim return 1; 162218885Sdim } else if ( this->seconds_ == that.seconds_ ) { 163218885Sdim if ( this->nanos_ >= that.nanos_ ) return 1; 164218885Sdim } 165218885Sdim return 0; 166218885Sdim } 167218885Sdim 168218885Sdim /// Determines if two TimeValue objects represent the same moment in time. 169243830Sdim /// @returns True iff *this == that. 170218885Sdim int operator == (const TimeValue &that) const { 171218885Sdim return (this->seconds_ == that.seconds_) && 172218885Sdim (this->nanos_ == that.nanos_); 173218885Sdim } 174218885Sdim 175218885Sdim /// Determines if two TimeValue objects represent times that are not the 176218885Sdim /// same. 177243830Sdim /// @returns True iff *this != that. 178218885Sdim int operator != (const TimeValue &that) const { return !(*this == that); } 179218885Sdim 180218885Sdim /// Adds two TimeValue objects together. 181218885Sdim /// @returns The sum of the two operands as a new TimeValue 182218885Sdim /// @brief Addition operator. 183218885Sdim friend TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2); 184218885Sdim 185218885Sdim /// Subtracts two TimeValue objects. 186218885Sdim /// @returns The difference of the two operands as a new TimeValue 187218885Sdim /// @brief Subtraction operator. 188218885Sdim friend TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2); 189218885Sdim 190218885Sdim /// @} 191218885Sdim /// @name Accessors 192218885Sdim /// @{ 193218885Sdim public: 194218885Sdim 195218885Sdim /// Returns only the seconds component of the TimeValue. The nanoseconds 196218885Sdim /// portion is ignored. No rounding is performed. 197218885Sdim /// @brief Retrieve the seconds component 198218885Sdim SecondsType seconds() const { return seconds_; } 199218885Sdim 200218885Sdim /// Returns only the nanoseconds component of the TimeValue. The seconds 201218885Sdim /// portion is ignored. 202218885Sdim /// @brief Retrieve the nanoseconds component. 203218885Sdim NanoSecondsType nanoseconds() const { return nanos_; } 204218885Sdim 205218885Sdim /// Returns only the fractional portion of the TimeValue rounded down to the 206218885Sdim /// nearest microsecond (divide by one thousand). 207218885Sdim /// @brief Retrieve the fractional part as microseconds; 208218885Sdim uint32_t microseconds() const { 209218885Sdim return nanos_ / NANOSECONDS_PER_MICROSECOND; 210218885Sdim } 211218885Sdim 212218885Sdim /// Returns only the fractional portion of the TimeValue rounded down to the 213218885Sdim /// nearest millisecond (divide by one million). 214218885Sdim /// @brief Retrieve the fractional part as milliseconds; 215218885Sdim uint32_t milliseconds() const { 216218885Sdim return nanos_ / NANOSECONDS_PER_MILLISECOND; 217218885Sdim } 218218885Sdim 219218885Sdim /// Returns the TimeValue as a number of microseconds. Note that the value 220218885Sdim /// returned can overflow because the range of a uint64_t is smaller than 221218885Sdim /// the range of a TimeValue. Nevertheless, this is useful on some operating 222218885Sdim /// systems and is therefore provided. 223218885Sdim /// @brief Convert to a number of microseconds (can overflow) 224218885Sdim uint64_t usec() const { 225218885Sdim return seconds_ * MICROSECONDS_PER_SECOND + 226218885Sdim ( nanos_ / NANOSECONDS_PER_MICROSECOND ); 227218885Sdim } 228218885Sdim 229218885Sdim /// Returns the TimeValue as a number of milliseconds. Note that the value 230218885Sdim /// returned can overflow because the range of a uint64_t is smaller than 231218885Sdim /// the range of a TimeValue. Nevertheless, this is useful on some operating 232218885Sdim /// systems and is therefore provided. 233218885Sdim /// @brief Convert to a number of milliseconds (can overflow) 234218885Sdim uint64_t msec() const { 235218885Sdim return seconds_ * MILLISECONDS_PER_SECOND + 236218885Sdim ( nanos_ / NANOSECONDS_PER_MILLISECOND ); 237218885Sdim } 238218885Sdim 239218885Sdim /// Converts the TimeValue into the corresponding number of "ticks" for 240218885Sdim /// Posix, correcting for the difference in Posix zero time. 241218885Sdim /// @brief Convert to unix time (100 nanoseconds since 12:00:00a Jan 1,1970) 242218885Sdim uint64_t toPosixTime() const { 243249423Sdim uint64_t result = seconds_ - PosixZeroTimeSeconds; 244218885Sdim result += nanos_ / NANOSECONDS_PER_POSIX_TICK; 245218885Sdim return result; 246218885Sdim } 247218885Sdim 248218885Sdim /// Converts the TimeValue into the corresponding number of seconds 249218885Sdim /// since the epoch (00:00:00 Jan 1,1970). 250218885Sdim uint64_t toEpochTime() const { 251249423Sdim return seconds_ - PosixZeroTimeSeconds; 252218885Sdim } 253218885Sdim 254218885Sdim /// Converts the TimeValue into the corresponding number of "ticks" for 255218885Sdim /// Win32 platforms, correcting for the difference in Win32 zero time. 256263508Sdim /// @brief Convert to Win32's FILETIME 257263508Sdim /// (100ns intervals since 00:00:00 Jan 1, 1601 UTC) 258218885Sdim uint64_t toWin32Time() const { 259263508Sdim uint64_t result = (uint64_t)10000000 * (seconds_ - Win32ZeroTimeSeconds); 260218885Sdim result += nanos_ / NANOSECONDS_PER_WIN32_TICK; 261218885Sdim return result; 262218885Sdim } 263218885Sdim 264218885Sdim /// Provides the seconds and nanoseconds as results in its arguments after 265218885Sdim /// correction for the Posix zero time. 266218885Sdim /// @brief Convert to timespec time (ala POSIX.1b) 267218885Sdim void getTimespecTime( uint64_t& seconds, uint32_t& nanos ) const { 268249423Sdim seconds = seconds_ - PosixZeroTimeSeconds; 269218885Sdim nanos = nanos_; 270218885Sdim } 271218885Sdim 272218885Sdim /// Provides conversion of the TimeValue into a readable time & date. 273218885Sdim /// @returns std::string containing the readable time value 274218885Sdim /// @brief Convert time to a string. 275218885Sdim std::string str() const; 276218885Sdim 277218885Sdim /// @} 278218885Sdim /// @name Mutators 279218885Sdim /// @{ 280218885Sdim public: 281218885Sdim /// The seconds component of the TimeValue is set to \p sec without 282218885Sdim /// modifying the nanoseconds part. This is useful for whole second 283218885Sdim /// arithmetic. 284218885Sdim /// @brief Set the seconds component. 285218885Sdim void seconds (SecondsType sec ) { 286218885Sdim this->seconds_ = sec; 287218885Sdim this->normalize(); 288218885Sdim } 289218885Sdim 290218885Sdim /// The nanoseconds component of the TimeValue is set to \p nanos without 291218885Sdim /// modifying the seconds part. This is useful for basic computations 292218885Sdim /// involving just the nanoseconds portion. Note that the TimeValue will be 293218885Sdim /// normalized after this call so that the fractional (nanoseconds) portion 294218885Sdim /// will have the smallest equivalent value. 295218885Sdim /// @brief Set the nanoseconds component using a number of nanoseconds. 296218885Sdim void nanoseconds ( NanoSecondsType nanos ) { 297218885Sdim this->nanos_ = nanos; 298218885Sdim this->normalize(); 299218885Sdim } 300218885Sdim 301218885Sdim /// The seconds component remains unchanged. 302218885Sdim /// @brief Set the nanoseconds component using a number of microseconds. 303218885Sdim void microseconds ( int32_t micros ) { 304218885Sdim this->nanos_ = micros * NANOSECONDS_PER_MICROSECOND; 305218885Sdim this->normalize(); 306218885Sdim } 307218885Sdim 308218885Sdim /// The seconds component remains unchanged. 309218885Sdim /// @brief Set the nanoseconds component using a number of milliseconds. 310218885Sdim void milliseconds ( int32_t millis ) { 311218885Sdim this->nanos_ = millis * NANOSECONDS_PER_MILLISECOND; 312218885Sdim this->normalize(); 313218885Sdim } 314218885Sdim 315218885Sdim /// @brief Converts from microsecond format to TimeValue format 316218885Sdim void usec( int64_t microseconds ) { 317218885Sdim this->seconds_ = microseconds / MICROSECONDS_PER_SECOND; 318218885Sdim this->nanos_ = NanoSecondsType(microseconds % MICROSECONDS_PER_SECOND) * 319218885Sdim NANOSECONDS_PER_MICROSECOND; 320218885Sdim this->normalize(); 321218885Sdim } 322218885Sdim 323218885Sdim /// @brief Converts from millisecond format to TimeValue format 324218885Sdim void msec( int64_t milliseconds ) { 325218885Sdim this->seconds_ = milliseconds / MILLISECONDS_PER_SECOND; 326218885Sdim this->nanos_ = NanoSecondsType(milliseconds % MILLISECONDS_PER_SECOND) * 327218885Sdim NANOSECONDS_PER_MILLISECOND; 328218885Sdim this->normalize(); 329218885Sdim } 330218885Sdim 331218885Sdim /// Converts the \p seconds argument from PosixTime to the corresponding 332218885Sdim /// TimeValue and assigns that value to \p this. 333218885Sdim /// @brief Convert seconds form PosixTime to TimeValue 334218885Sdim void fromEpochTime( SecondsType seconds ) { 335249423Sdim seconds_ = seconds + PosixZeroTimeSeconds; 336218885Sdim nanos_ = 0; 337218885Sdim this->normalize(); 338218885Sdim } 339218885Sdim 340218885Sdim /// Converts the \p win32Time argument from Windows FILETIME to the 341218885Sdim /// corresponding TimeValue and assigns that value to \p this. 342218885Sdim /// @brief Convert seconds form Windows FILETIME to TimeValue 343218885Sdim void fromWin32Time( uint64_t win32Time ) { 344249423Sdim this->seconds_ = win32Time / 10000000 + Win32ZeroTimeSeconds; 345218885Sdim this->nanos_ = NanoSecondsType(win32Time % 10000000) * 100; 346218885Sdim } 347218885Sdim 348218885Sdim /// @} 349218885Sdim /// @name Implementation 350218885Sdim /// @{ 351218885Sdim private: 352218885Sdim /// This causes the values to be represented so that the fractional 353218885Sdim /// part is minimized, possibly incrementing the seconds part. 354218885Sdim /// @brief Normalize to canonical form. 355218885Sdim void normalize(); 356218885Sdim 357218885Sdim /// @} 358218885Sdim /// @name Data 359218885Sdim /// @{ 360218885Sdim private: 361218885Sdim /// Store the values as a <timeval>. 362218885Sdim SecondsType seconds_;///< Stores the seconds part of the TimeVal 363218885Sdim NanoSecondsType nanos_; ///< Stores the nanoseconds part of the TimeVal 364249423Sdim 365249423Sdim static const SecondsType PosixZeroTimeSeconds; 366249423Sdim static const SecondsType Win32ZeroTimeSeconds; 367218885Sdim /// @} 368218885Sdim 369218885Sdim }; 370218885Sdim 371218885Sdiminline TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2) { 372218885Sdim TimeValue sum (tv1.seconds_ + tv2.seconds_, tv1.nanos_ + tv2.nanos_); 373218885Sdim sum.normalize (); 374218885Sdim return sum; 375218885Sdim} 376218885Sdim 377218885Sdiminline TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2) { 378218885Sdim TimeValue difference (tv1.seconds_ - tv2.seconds_, tv1.nanos_ - tv2.nanos_ ); 379218885Sdim difference.normalize (); 380218885Sdim return difference; 381218885Sdim} 382218885Sdim 383218885Sdim} 384218885Sdim} 385218885Sdim 386218885Sdim#endif 387