summaryrefslogtreecommitdiff
path: root/ACE/ace/High_Res_Timer.inl
blob: 34dc21d383b47570947ec0b657c607484d5d4e94 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// -*- C++ -*- */
#include "ace/Global_Macros.h"

#if defined (ACE_WIN32)
#  include "ace/OS_NS_sys_time.h"
#endif /* ACE_WIN32 */

ACE_BEGIN_VERSIONED_NAMESPACE_DECL

/// Be very careful before changing the calculations inside
/// ACE_High_Res_Timer. The precision matters and we are using integer
/// calculations not floating point.
ACE_INLINE void
ACE_High_Res_Timer::hrtime_to_tv (ACE_Time_Value &tv,
                                  const ACE_hrtime_t hrt)
{
#if !defined (ACE_WIN32)
    // The following are based on the units of global_scale_factor_
    // being 1/microsecond.  Therefore, dividing by it converts
    // clock ticks to microseconds.
    tv.sec ((time_t) (hrt / (ACE_UINT32) ACE_HR_SCALE_CONVERSION /
                  global_scale_factor ()));

    // hrt = (tv.sec * ACE_ONE_SECOND_IN_USECS + tv.usec) * global_scale_factor_
    // tv.usec = hrt / global_scale_factor_ - tv.sec * ACE_ONE_SECOND_IN_USECS
    // That first term will be lossy, so factor out global_scale_factor_:
    // tv.usec = (hrt - tv.sec * ACE_ONE_SECOND_IN_USECS * global_scale_factor_)/
    //           global_scale_factor
    ACE_hrtime_t tmp = tv.sec ();
    tmp *= ((ACE_UINT32) ACE_HR_SCALE_CONVERSION * global_scale_factor ());
    tv.usec ((suseconds_t) ((hrt - tmp) / global_scale_factor ()));
#else
    // This a higher-precision version, specific for Windows systems
    // The following are based on the units of global_scale_factor_
    // being 1/microsecond.  Therefore, dividing by it converts
    // clock ticks to microseconds.
    tv.sec ((time_t) (hrt / global_scale_factor () ));

    // Calculate usec, first calculate the seconds in hrtime
    ACE_High_Res_Timer::global_scale_factor_type tmp = tv.sec ();
    tmp *= global_scale_factor ();
    tv.usec ((suseconds_t) ((hrt - tmp) * ACE_HR_SCALE_CONVERSION / global_scale_factor ()));
#endif
}


ACE_INLINE ACE_Time_Value
ACE_High_Res_Timer::gettimeofday (const ACE_OS::ACE_HRTimer_Op op)
{
#if defined (ACE_WIN32)
  // Get the global scale factor if there isn't one yet.
  if (ACE_High_Res_Timer::global_scale_factor_status_ == 0)
    ACE_High_Res_Timer::global_scale_factor ();

  // If there isn't a high-res timer, use gettimeofday ();
  if (ACE_High_Res_Timer::global_scale_factor_status_ == -1)
    return ACE_OS::gettimeofday ();
#endif /* ACE_WIN32 */

  ACE_Time_Value tv;
  ACE_High_Res_Timer::hrtime_to_tv (tv, ACE_OS::gethrtime (op));
  return tv;
}

/// Get the current high res timer as the time of day. This is intended
/// to be used for a gettimeofday replacement in ACE_Timer_Queue and
/// derived classes so the timers will be based on high res timers rather
/// than wall clock time. It uses the ACE_High_Res_Timer::gettimeofday
/// function, which is deprecated. If it gets removed, please move the
/// code down here, intact.
ACE_INLINE ACE_Time_Value
ACE_High_Res_Timer::gettimeofday_hr ()
{
  return ACE_High_Res_Timer::gettimeofday ();
}


ACE_INLINE ACE_hrtime_t
ACE_High_Res_Timer::gettime (const ACE_OS::ACE_HRTimer_Op op)
{
#if defined (ACE_WIN32)
  // Get the global scale factor if there isn't one yet.
  if (ACE_High_Res_Timer::global_scale_factor_status_ == 0)
    ACE_High_Res_Timer::global_scale_factor ();

  // If there isn't a high-res timer, use gettimeofday ();
  if (ACE_High_Res_Timer::global_scale_factor_status_ == -1)
    {
      ACE_Time_Value const tv = ACE_OS::gettimeofday ();
      // Return the time in microseconds because the global_scale_factor_
      // is 1.
      return tv.sec () * ACE_ONE_SECOND_IN_USECS + tv.usec ();
    }
#endif /* ACE_WIN32 */

  return ACE_OS::gethrtime (op);
}

ACE_INLINE ACE_hrtime_t
ACE_High_Res_Timer::elapsed_hrtime (const ACE_hrtime_t end,
                                    const ACE_hrtime_t start)
{
  if (end > start)
    return end - start;
  return (~start + 1 + end);     // Wrapped-around counter diff
}

ACE_INLINE
ACE_High_Res_Timer::~ACE_High_Res_Timer ()
{
}

ACE_INLINE void
ACE_High_Res_Timer::start (const ACE_OS::ACE_HRTimer_Op op)
{
  ACE_TRACE ("ACE_High_Res_Timer::start");
  this->start_ = ACE_High_Res_Timer::gettime (op);
}

ACE_INLINE void
ACE_High_Res_Timer::stop (const ACE_OS::ACE_HRTimer_Op op)
{
  ACE_TRACE ("ACE_High_Res_Timer::stop");
  this->end_ = ACE_High_Res_Timer::gettime (op);
}

ACE_INLINE void
ACE_High_Res_Timer::start_incr (const ACE_OS::ACE_HRTimer_Op op)
{
  ACE_TRACE ("ACE_High_Res_Timer::start_incr");
  this->start_incr_ = ACE_High_Res_Timer::gettime (op);
}

ACE_INLINE void
ACE_High_Res_Timer::stop_incr (const ACE_OS::ACE_HRTimer_Op op)
{
  ACE_TRACE ("ACE_High_Res_Timer::stop_incr");
  this->total_ +=
    ACE_High_Res_Timer::elapsed_hrtime (ACE_High_Res_Timer::gettime (op),
                                        this->start_incr_);
}

ACE_INLINE void
ACE_High_Res_Timer::elapsed_microseconds (ACE_hrtime_t &usecs) const
{

#if !defined (ACE_WIN32)
  ACE_hrtime_t elapsed = ACE_High_Res_Timer::elapsed_hrtime (this->end_,
                                                             this->start_);
  usecs = (ACE_hrtime_t) (elapsed / global_scale_factor ());
#else
  usecs = (ACE_High_Res_Timer::elapsed_hrtime (this->end_, this->start_) *
           ACE_HR_SCALE_CONVERSION) /
          global_scale_factor ();
#endif
}

ACE_INLINE void
ACE_High_Res_Timer::global_scale_factor (
    ACE_High_Res_Timer::global_scale_factor_type gsf)
{
  global_scale_factor_ = gsf;
}

ACE_END_VERSIONED_NAMESPACE_DECL