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