blob: ca56e30c7090b0842f47698f0857836aac8a63d2 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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>
Greg Clayton7b0992d2013-04-18 22:45:39 +000019#include <memory>
Greg Claytone01e07b2013-04-18 18:10:51 +000020#include "DNBDefs.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021#include "PThreadMutex.h"
22
23class DNBTimer
24{
25public:
26 //------------------------------------------------------------------
27 // Constructors and Destructors
28 //------------------------------------------------------------------
29 DNBTimer (bool threadSafe) :
30 m_mutexAP()
31 {
32 if (threadSafe)
33 m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
34 Reset();
35 }
36
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
57 ~DNBTimer ()
58 {
59 }
60
61 bool
62 IsThreadSafe() const
63 {
64 return m_mutexAP.get() != NULL;
65 }
66 //------------------------------------------------------------------
67 // Reset the time value to now
68 //------------------------------------------------------------------
69 void
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
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
Greg Claytonee2ed522015-03-09 19:45:23 +000086 GetTime (uint64_t& sec, uint32_t& usec) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +000087 {
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
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
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 }
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 }
155protected:
156 //------------------------------------------------------------------
157 // Classes that inherit from DNBTimer can see and modify these
158 //------------------------------------------------------------------
Greg Clayton7b0992d2013-04-18 22:45:39 +0000159 std::unique_ptr<PThreadMutex> m_mutexAP;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000160 struct timeval m_timeval;
161};
162
163#endif // #ifndef __DNBTimer_h__