1 //===-- DNBTimer.h ----------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  Created by Greg Clayton on 12/13/07.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef __DNBTimer_h__
15 #define __DNBTimer_h__
16 
17 #include <sys/time.h>
18 #include <stdint.h>
19 #include <memory>
20 #include "PThreadMutex.h"
21 
22 class DNBTimer
23 {
24 public:
25     //------------------------------------------------------------------
26     // Constructors and Destructors
27     //------------------------------------------------------------------
28     DNBTimer (bool threadSafe) :
29             m_mutexAP()
30         {
31             if (threadSafe)
32                 m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
33             Reset();
34         }
35 
36     DNBTimer (const DNBTimer& rhs) :
37             m_mutexAP()
38         {
39             // Create a new mutex to make this timer thread safe as well if
40             // the timer we are copying is thread safe
41             if (rhs.IsThreadSafe())
42                 m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
43             m_timeval = rhs.m_timeval;
44         }
45 
46     DNBTimer& operator= (const DNBTimer& rhs)
47         {
48             // Create a new mutex to make this timer thread safe as well if
49             // the timer we are copying is thread safe
50             if (rhs.IsThreadSafe())
51                 m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
52             m_timeval = rhs.m_timeval;
53             return *this;
54         }
55 
56     ~DNBTimer ()
57         {
58         }
59 
60         bool
61         IsThreadSafe() const
62         {
63             return m_mutexAP.get() != NULL;
64         }
65         //------------------------------------------------------------------
66         // Reset the time value to now
67         //------------------------------------------------------------------
68         void
69         Reset ()
70         {
71             PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get());
72             gettimeofday (&m_timeval, NULL);
73         }
74         //------------------------------------------------------------------
75         // Get the total mircoseconds since Jan 1, 1970
76         //------------------------------------------------------------------
77         uint64_t
78         TotalMicroSeconds () const
79         {
80             PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get());
81             return (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec;
82         }
83 
84         void
85         GetTime (uint32_t& sec, uint32_t& usec) const
86         {
87             PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get());
88             sec = m_timeval.tv_sec;
89             usec = m_timeval.tv_usec;
90         }
91         //------------------------------------------------------------------
92         // Return the number of microseconds elapsed between now and the
93         // m_timeval
94         //------------------------------------------------------------------
95         uint64_t
96         ElapsedMicroSeconds (bool update)
97         {
98             PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get());
99             struct timeval now;
100             gettimeofday (&now, NULL);
101             uint64_t now_usec = (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec;
102             uint64_t this_usec = (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec;
103             uint64_t elapsed = now_usec - this_usec;
104             // Update the timer time value if requeseted
105             if (update)
106                 m_timeval = now;
107             return elapsed;
108         }
109 
110         static uint64_t GetTimeOfDay()
111         {
112             struct timeval now;
113             gettimeofday (&now, NULL);
114             uint64_t now_usec = (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec;
115             return now_usec;
116         }
117 
118         static void OffsetTimeOfDay (struct timespec* ts, __darwin_time_t sec_offset = 0, long nsec_offset = 0)
119         {
120             if (ts == NULL)
121                 return;
122             // Get the current time in a timeval structure
123             struct timeval now;
124             gettimeofday (&now, NULL);
125             // Morph it into a timespec
126             TIMEVAL_TO_TIMESPEC(&now, ts);
127             // Offset the timespec if requested
128             if (sec_offset != 0 || nsec_offset != 0)
129             {
130                 // Offset the nano seconds
131                 ts->tv_nsec += nsec_offset;
132                 // Offset the seconds taking into account a nano-second overflow
133                 ts->tv_sec = ts->tv_sec + ts->tv_nsec / 1000000000 + sec_offset;
134                 // Trim the nanoseconds back there was an overflow
135                 ts->tv_nsec = ts->tv_nsec % 1000000000;
136             }
137         }
138         static bool TimeOfDayLaterThan (struct timespec &ts)
139         {
140             struct timespec now;
141             OffsetTimeOfDay(&now);
142             if (now.tv_sec > ts.tv_sec)
143                 return true;
144             else if (now.tv_sec < ts.tv_sec)
145                 return false;
146             else
147             {
148                 if (now.tv_nsec > ts.tv_nsec)
149                     return true;
150                 else
151                     return false;
152             }
153         }
154 protected:
155     //------------------------------------------------------------------
156     // Classes that inherit from DNBTimer can see and modify these
157     //------------------------------------------------------------------
158         std::auto_ptr<PThreadMutex> m_mutexAP;
159         struct timeval  m_timeval;
160 };
161 
162 #endif // #ifndef __DNBTimer_h__
163