b3Clock.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. #include "b3Clock.h"
  2. template <class T>
  3. const T& b3ClockMin(const T& a, const T& b)
  4. {
  5. return a < b ? a : b ;
  6. }
  7. #ifdef __CELLOS_LV2__
  8. #include <sys/sys_time.h>
  9. #include <sys/time_util.h>
  10. #include <stdio.h>
  11. #endif
  12. #if defined (SUNOS) || defined (__SUNOS__)
  13. #include <stdio.h>
  14. #endif
  15. #if defined(WIN32) || defined(_WIN32)
  16. #define B3_USE_WINDOWS_TIMERS
  17. #define WIN32_LEAN_AND_MEAN
  18. #define NOWINRES
  19. #define NOMCX
  20. #define NOIME
  21. #ifdef _XBOX
  22. #include <Xtl.h>
  23. #else //_XBOX
  24. #include <windows.h>
  25. #endif //_XBOX
  26. #include <time.h>
  27. #else //_WIN32
  28. #include <sys/time.h>
  29. #include <unistd.h>
  30. #endif //_WIN32
  31. struct b3ClockData
  32. {
  33. #ifdef B3_USE_WINDOWS_TIMERS
  34. LARGE_INTEGER mClockFrequency;
  35. DWORD mStartTick;
  36. LONGLONG mPrevElapsedTime;
  37. LARGE_INTEGER mStartTime;
  38. #else
  39. #ifdef __CELLOS_LV2__
  40. uint64_t mStartTime;
  41. #else
  42. struct timeval mStartTime;
  43. #endif
  44. #endif //__CELLOS_LV2__
  45. };
  46. ///The b3Clock is a portable basic clock that measures accurate time in seconds, use for profiling.
  47. b3Clock::b3Clock()
  48. {
  49. m_data = new b3ClockData;
  50. #ifdef B3_USE_WINDOWS_TIMERS
  51. QueryPerformanceFrequency(&m_data->mClockFrequency);
  52. #endif
  53. reset();
  54. }
  55. b3Clock::~b3Clock()
  56. {
  57. delete m_data;
  58. }
  59. b3Clock::b3Clock(const b3Clock& other)
  60. {
  61. m_data = new b3ClockData;
  62. *m_data = *other.m_data;
  63. }
  64. b3Clock& b3Clock::operator=(const b3Clock& other)
  65. {
  66. *m_data = *other.m_data;
  67. return *this;
  68. }
  69. /// Resets the initial reference time.
  70. void b3Clock::reset()
  71. {
  72. #ifdef B3_USE_WINDOWS_TIMERS
  73. QueryPerformanceCounter(&m_data->mStartTime);
  74. m_data->mStartTick = GetTickCount();
  75. m_data->mPrevElapsedTime = 0;
  76. #else
  77. #ifdef __CELLOS_LV2__
  78. typedef uint64_t ClockSize;
  79. ClockSize newTime;
  80. //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
  81. SYS_TIMEBASE_GET( newTime );
  82. m_data->mStartTime = newTime;
  83. #else
  84. gettimeofday(&m_data->mStartTime, 0);
  85. #endif
  86. #endif
  87. }
  88. /// Returns the time in ms since the last call to reset or since
  89. /// the b3Clock was created.
  90. unsigned long int b3Clock::getTimeMilliseconds()
  91. {
  92. #ifdef B3_USE_WINDOWS_TIMERS
  93. LARGE_INTEGER currentTime;
  94. QueryPerformanceCounter(&currentTime);
  95. LONGLONG elapsedTime = currentTime.QuadPart -
  96. m_data->mStartTime.QuadPart;
  97. // Compute the number of millisecond ticks elapsed.
  98. unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
  99. m_data->mClockFrequency.QuadPart);
  100. // Check for unexpected leaps in the Win32 performance counter.
  101. // (This is caused by unexpected data across the PCI to ISA
  102. // bridge, aka south bridge. See Microsoft KB274323.)
  103. unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick;
  104. signed long msecOff = (signed long)(msecTicks - elapsedTicks);
  105. if (msecOff < -100 || msecOff > 100)
  106. {
  107. // Adjust the starting time forwards.
  108. LONGLONG msecAdjustment = b3ClockMin(msecOff *
  109. m_data->mClockFrequency.QuadPart / 1000, elapsedTime -
  110. m_data->mPrevElapsedTime);
  111. m_data->mStartTime.QuadPart += msecAdjustment;
  112. elapsedTime -= msecAdjustment;
  113. // Recompute the number of millisecond ticks elapsed.
  114. msecTicks = (unsigned long)(1000 * elapsedTime /
  115. m_data->mClockFrequency.QuadPart);
  116. }
  117. // Store the current elapsed time for adjustments next time.
  118. m_data->mPrevElapsedTime = elapsedTime;
  119. return msecTicks;
  120. #else
  121. #ifdef __CELLOS_LV2__
  122. uint64_t freq=sys_time_get_timebase_frequency();
  123. double dFreq=((double) freq) / 1000.0;
  124. typedef uint64_t ClockSize;
  125. ClockSize newTime;
  126. SYS_TIMEBASE_GET( newTime );
  127. //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
  128. return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
  129. #else
  130. struct timeval currentTime;
  131. gettimeofday(&currentTime, 0);
  132. return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 +
  133. (currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000;
  134. #endif //__CELLOS_LV2__
  135. #endif
  136. }
  137. /// Returns the time in us since the last call to reset or since
  138. /// the Clock was created.
  139. unsigned long long int b3Clock::getTimeMicroseconds()
  140. {
  141. #ifdef B3_USE_WINDOWS_TIMERS
  142. LARGE_INTEGER currentTime;
  143. QueryPerformanceCounter(&currentTime);
  144. LONGLONG elapsedTime = currentTime.QuadPart -
  145. m_data->mStartTime.QuadPart;
  146. // Compute the number of millisecond ticks elapsed.
  147. unsigned long long msecTicks = (unsigned long long)(1000 * elapsedTime /
  148. m_data->mClockFrequency.QuadPart);
  149. // Check for unexpected leaps in the Win32 performance counter.
  150. // (This is caused by unexpected data across the PCI to ISA
  151. // bridge, aka south bridge. See Microsoft KB274323.)
  152. unsigned long long elapsedTicks = GetTickCount() - m_data->mStartTick;
  153. signed long long msecOff = (signed long)(msecTicks - elapsedTicks);
  154. if (msecOff < -100 || msecOff > 100)
  155. {
  156. // Adjust the starting time forwards.
  157. LONGLONG msecAdjustment = b3ClockMin(msecOff *
  158. m_data->mClockFrequency.QuadPart / 1000, elapsedTime -
  159. m_data->mPrevElapsedTime);
  160. m_data->mStartTime.QuadPart += msecAdjustment;
  161. elapsedTime -= msecAdjustment;
  162. }
  163. // Store the current elapsed time for adjustments next time.
  164. m_data->mPrevElapsedTime = elapsedTime;
  165. // Convert to microseconds.
  166. unsigned long long usecTicks = (unsigned long)(1000000 * elapsedTime /
  167. m_data->mClockFrequency.QuadPart);
  168. return usecTicks;
  169. #else
  170. #ifdef __CELLOS_LV2__
  171. uint64_t freq=sys_time_get_timebase_frequency();
  172. double dFreq=((double) freq)/ 1000000.0;
  173. typedef uint64_t ClockSize;
  174. ClockSize newTime;
  175. //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
  176. SYS_TIMEBASE_GET( newTime );
  177. return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
  178. #else
  179. struct timeval currentTime;
  180. gettimeofday(&currentTime, 0);
  181. return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 +
  182. (currentTime.tv_usec - m_data->mStartTime.tv_usec);
  183. #endif//__CELLOS_LV2__
  184. #endif
  185. }
  186. double b3Clock::getTimeInSeconds()
  187. {
  188. return double(getTimeMicroseconds()/1.e6);
  189. }
  190. void b3Clock::usleep(int microSeconds)
  191. {
  192. #ifdef _WIN32
  193. int millis = microSeconds/1000;
  194. if (millis < 1)
  195. {
  196. millis = 1;
  197. }
  198. Sleep(millis);
  199. #else
  200. ::usleep(microSeconds);
  201. //struct timeval tv;
  202. //tv.tv_sec = microSeconds/1000000L;
  203. //tv.tv_usec = microSeconds%1000000L;
  204. //return select(0, 0, 0, 0, &tv);
  205. #endif
  206. }