[7297] Fixed profession spells sorting in trainer spell list at client.
[getmangos.git] / dep / ACE_wrappers / ace / High_Res_Timer.h
blob482205f1376373ad306fe18fc6ec5524b271b430
1 // -*- C++ -*-
3 //==========================================================================
4 /**
5 * @file High_Res_Timer.h
7 * $Id: High_Res_Timer.h 81286 2008-04-09 07:27:30Z johnnyw $
9 * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
11 //==========================================================================
13 #ifndef ACE_HIGH_RES_TIMER_H
14 #define ACE_HIGH_RES_TIMER_H
15 #include /**/ "ace/pre.h"
17 #include /**/ "ace/ACE_export.h"
19 #if !defined (ACE_LACKS_PRAGMA_ONCE)
20 # pragma once
21 #endif /* ACE_LACKS_PRAGMA_ONCE */
23 #include "ace/Basic_Types.h"
24 #include "ace/OS_NS_time.h"
25 #include "ace/Time_Value.h"
27 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
29 /**
30 * @class ACE_High_Res_Timer
32 * @brief A high resolution timer class wrapper that encapsulates
33 * OS-specific high-resolution timers, such as those found on
34 * Solaris, AIX, Win32/Pentium, and VxWorks.
36 * Most of the member functions don't return values. The only
37 * reason that one would fail is if high-resolution time isn't
38 * supported on the platform. To avoid impacting performance
39 * and complicating the interface, in that case,
40 * <ACE_OS::gettimeofday> is used instead.
41 * The global scale factor is required for platforms that have
42 * high-resolution timers that return units other than
43 * microseconds, such as clock ticks. It is represented as a
44 * static u_long, can only be accessed through static methods,
45 * and is used by all instances of High Res Timer. The member
46 * functions that return or print times use the global scale
47 * factor. They divide the "time" that they get from
48 * <ACE_OS::gethrtime> by global_scale_factor_ to obtain the
49 * time in microseconds. Its units are therefore 1/microsecond.
50 * On Windows the global_scale_factor_ units are 1/millisecond.
51 * There's a macro <ACE_HR_SCALE_CONVERSION> which gives the
52 * units/second. Because it's possible that the units/second
53 * changes in the future, it's recommended to use it instead
54 * of a "hard coded" solution.
55 * Dependend on the platform and used class members, there's a
56 * maximum elapsed period before overflow (which is not checked).
57 * Look at the documentation with some members functions.
58 * On some (most?) implementations it's not recommended to measure
59 * "long" timeperiods, because the error's can accumulate fast.
60 * This is probably not a problem profiling code, but could be
61 * on if the high resolution timer class is used to initiate
62 * actions after a "long" timeout.
63 * On Solaris, a scale factor of 1000 should be used because its
64 * high-resolution timer returns nanoseconds. However, on Intel
65 * platforms, we use RDTSC which returns the number of clock
66 * ticks since system boot. For a 200MHz cpu, each clock tick
67 * is 1/200 of a microsecond; the global_scale_factor_ should
68 * therefore be 200 or 200000 if it's in unit/millisecond.
69 * On Windows ::QueryPerformanceCounter() is used, which can be a
70 * different implementation depending on the used windows HAL
71 * (Hardware Abstraction Layer). On some it uses the PC "timer chip"
72 * while it uses RDTSC on others.
73 * @note The elapsed time calculations in the print methods use
74 * ACE_hrtime_t values. Those methods do _not_ check for overflow!
75 * @note Gabe <begeddov@proaxis.com> raises this issue regarding
76 * <ACE_OS::gethrtime>: on multi-processors, the processor that
77 * you query for your <timer.stop> value might not be the one
78 * you queried for <timer.start>. Its not clear how much
79 * divergence there would be, if any.
80 * This issue is not mentioned in the Solaris 2.5.1 gethrtime
81 * man page.
82 * A RDTSC NOTE: RDTSC is the Intel Pentium read-time stamp counter
83 * and is actualy a 64 bit clock cycle counter, which is increased
84 * with every cycle. It has a low overhead and can be read within
85 * 16 (pentium) or 32 (pentium II,III,...) cycles, but it doesn't
86 * serialize the processor, which could give wrong timings when
87 * profiling very short code fragments.
88 * Problematic is that some power sensitive devices
89 * (laptops for example, but probably also embedded devices),
90 * do change the cycle rate while running.
91 * Some pentiums can run on (at least) two clock frequency's.
92 * Another problem arises with multiprocessor computers, there
93 * are reports that the different RDTSC's are not always kept
94 * in sync.
95 * A windows "timer chip" NOTE: (8254-compatible real-time clock)
96 * When ::QueryPerformanceCounter() uses the 8254 it has a
97 * frequency off about 1.193 Mhz (or sometimes 3.579 Mhz?) and
98 * reading it requires some time (several thousand cycles).
100 class ACE_Export ACE_High_Res_Timer
102 public:
103 // = Initialization method.
106 * global_scale_factor_ is set to @a gsf. All High_Res_Timers use
107 * global_scale_factor_. This allows applications to set the scale
108 * factor just once for all High_Res_Timers. Check
109 * High_Res_Timer.cpp for the default global_scale_factors for
110 * several platforms. For many platforms (e.g., Solaris), the
111 * global_scale_factor_ is set to 1000 so that <scale_factor> need
112 * not be set. Careful, a <scale_factor> of 0 will cause division
113 * by zero exceptions.
114 * Depending on the platform its units are 1/microsecond or
115 * 1/millisecond. Use <ACE_HR_SCALE_CONVERSION> inside calculations
116 * instead a hardcoded value.
118 static void global_scale_factor (ACE_UINT32 gsf);
120 /// Returns the global_scale_factor.
121 static ACE_UINT32 global_scale_factor (void);
123 #ifndef ACE_HR_SCALE_CONVERSION
124 # define ACE_HR_SCALE_CONVERSION (ACE_ONE_SECOND_IN_USECS)
125 #endif /* ACE_HR_SCALE_CONVERSION */
128 * Sets the global_scale_factor to the value in the @a env
129 * environment variable. Returns 0 on success, -1 on failure.
130 * @note If @a env points to string "0" (value zero), this call will fail.
131 * This is basically a no-op on CE because there is no concept of
132 * environment variable on CE.
134 static int get_env_global_scale_factor (const ACE_TCHAR *env
135 = ACE_TEXT ("ACE_SCALE_FACTOR"));
138 * Set (and return, for info) the global scale factor by sleeping
139 * for @a usec and counting the number of intervening clock cycles.
140 * Average over @a iterations of @a usec each. On some platforms,
141 * such as Pentiums, this is called automatically during the first
142 * ACE_High_Res_Timer construction with the default parameter
143 * values. An application can override that by calling calibrate
144 * with any desired parameter values _prior_ to constructing the
145 * first ACE_High_Res_Timer instance.
146 * Beware for platforms that can change the cycle rate on the fly.
148 static ACE_UINT32 calibrate (const ACE_UINT32 usec = 500000,
149 const u_int iterations = 10);
151 /// Initialize the timer.
152 ACE_High_Res_Timer (void);
154 /// Destructor.
155 ~ACE_High_Res_Timer (void);
157 /// Reinitialize the timer.
158 void reset (void);
160 /// Start timing.
161 void start (const ACE_OS::ACE_HRTimer_Op = ACE_OS::ACE_HRTIMER_GETTIME);
163 /// Stop timing.
164 void stop (const ACE_OS::ACE_HRTimer_Op = ACE_OS::ACE_HRTIMER_GETTIME);
166 /// Set @a tv to the number of microseconds elapsed.
168 * Could overflow within hours on windows with emulated 64 bit int's
169 * and a fast counter. VC++ and Borland normaly use __int64 and
170 * so normaly don't have this problem.
172 void elapsed_time (ACE_Time_Value &tv) const;
174 /// Set @a nanoseconds to the number of nanoseconds elapsed.
176 * Will overflow when measuring more than 194 day's.
178 void elapsed_time (ACE_hrtime_t &nanoseconds) const;
180 #if defined (ACE_HAS_POSIX_TIME)
181 /// Returns the elapsed (stop - start) time in a struct timespec
182 /// (sec, nsec).
183 void elapsed_time (struct timespec &) const;
184 #endif /* ACE_HAS_POSIX_TIME */
186 /// Sets @a usecs to the elapsed (stop - start) time in microseconds.
188 * Will overflow on windows when measuring more than appox. 2^^54 ticks.
189 * Is still more than 48 days with a 4 Ghz counter.
191 void elapsed_microseconds (ACE_hrtime_t &usecs) const;
193 /// Start incremental timing.
194 void start_incr (const ACE_OS::ACE_HRTimer_Op = ACE_OS::ACE_HRTIMER_GETTIME);
196 /// Stop incremental timing.
197 void stop_incr (const ACE_OS::ACE_HRTimer_Op = ACE_OS::ACE_HRTIMER_GETTIME);
199 /// Set @a tv to the number of microseconds elapsed between all calls
200 /// to start_incr and stop_incr.
201 void elapsed_time_incr (ACE_Time_Value &tv) const;
203 /// Set <nsec> to the number of nanoseconds elapsed between all calls
204 /// to start_incr and stop_incr.
205 void elapsed_time_incr (ACE_hrtime_t &nanoseconds) const;
207 #if !defined (ACE_HAS_WINCE)
208 // @@ WINCE These two functions are currently not supported on Windows CE.
209 // However, we should probably use the handle and ACE_Log_Msg to
210 // print out the result.
211 /// Print total time.
212 /// @note only use <print_total> if incremental timings had been used!
213 void print_total (const ACE_TCHAR *message,
214 const int iterations = 1,
215 ACE_HANDLE handle = ACE_STDOUT) const;
217 /// Print average time.
218 void print_ave (const ACE_TCHAR *message,
219 const int iterations = 1,
220 ACE_HANDLE handle = ACE_STDOUT) const;
221 #endif /* !ACE_HAS_WINCE */
223 /// Dump the state of an object.
224 void dump (void) const;
226 /// Declare the dynamic allocation hooks.
227 ACE_ALLOC_HOOK_DECLARE;
230 * Get the current "time" as the high resolution counter at this time.
231 * This is intended to be useful for supplying to a ACE_Timer_Queue
232 * as the gettimeofday function, thereby basing the timer calculations
233 * on the high res timer rather than wall clock time.
235 static ACE_Time_Value gettimeofday_hr (void);
238 * @deprecated THIS FUNCTION IS DEPRECATED. PLEASE USE
239 * <ACE_OS::gettimeofday> INSTEAD! Calls <ACE_High_Res_Timer::hrtime_to_tv>
240 * passing <ACE_OS::gethrtime>. This function can be used to parameterize
241 * objects such as <ACE_Timer_Queue::gettimeofday>. If
242 * <global_scale_factor_> is not set, and we're on a platform that
243 * requires <global_scale_factor_> (e.g., Win32),
244 * ACE_OS::gettimeofday will be used instead of <ACE_OS::gethrtime>.
245 * This allows applications on Intel to use <High_Res_Timer> even
246 * when <global_scale_factor> is not set. However, setting the
247 * <global_scale_factor_> appropriately will result in the finest
248 * resolution possible.
250 static ACE_Time_Value gettimeofday (const ACE_OS::ACE_HRTimer_Op =
251 ACE_OS::ACE_HRTIMER_GETTIME);
253 /// Converts an @a hrt to @a tv using global_scale_factor_.
254 static void hrtime_to_tv (ACE_Time_Value &tv,
255 const ACE_hrtime_t hrt);
257 #if defined (linux)
259 * This is used to find out the Mhz of the machine for the scale
260 * factor. If there are any problems getting it, we just return 1
261 * (the default).
263 static ACE_UINT32 get_cpuinfo (void);
264 #endif /* defined (linux) */
266 private:
268 * For internal use: gets the high-resolution time using
269 * <ACE_OS::gethrtime>. Except on platforms that require that the
270 * <global_scale_factor_> be set, such as ACE_WIN32, uses the
271 * low-resolution clock if the <global_scale_factor_> has not been
272 * set.
274 static ACE_hrtime_t gettime (const ACE_OS::ACE_HRTimer_Op =
275 ACE_OS::ACE_HRTIMER_GETTIME);
277 /// Calculate the difference between two ACE_hrtime_t values. It is assumed
278 /// that the end time is later than start time, so if end is a smaller
279 /// value, the time counter has wrapped around.
280 static ACE_hrtime_t elapsed_hrtime (const ACE_hrtime_t end,
281 const ACE_hrtime_t start);
283 /// Starting time.
284 ACE_hrtime_t start_;
286 /// Ending time.
287 ACE_hrtime_t end_;
289 /// Total elapsed time.
290 ACE_hrtime_t total_;
292 /// Start time of incremental timing.
293 ACE_hrtime_t start_incr_;
295 /// Converts ticks to microseconds. That is, ticks /
296 /// global_scale_factor_ == microseconds.
297 static ACE_UINT32 global_scale_factor_;
300 * Indicates the status of the global scale factor,
301 * 0 = hasn't been set
302 * 1 = been set
303 * -1 = HR timer not supported
305 static int global_scale_factor_status_;
308 ACE_END_VERSIONED_NAMESPACE_DECL
310 #if defined (__ACE_INLINE__)
311 #include "ace/High_Res_Timer.inl"
312 #endif /* __ACE_INLINE__ */
314 #include /**/ "ace/post.h"
315 #endif /* ACE_HIGH_RES_TIMER_H */