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