cputime.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. #include "precompile.h"
  2. #include "cputime.h"
  3. #include "memutil.h"
  4. #include "intalgo.h"
  5. #ifdef _WIN32
  6. #include <Mmsystem.h>
  7. #endif
  8. #include <assert.h>
  9. //define it at CMakeLists.txt
  10. //#pragma comment(lib, "Winmm.lib")
  11. static LARGE_INTEGER cpu_freq = {0};
  12. TOOLKIT_API cputime_t cputime_now()
  13. {
  14. LARGE_INTEGER now;
  15. QueryPerformanceCounter(&now);
  16. return (__int64)now.QuadPart;
  17. }
  18. TOOLKIT_API cputime_t cputime_per_usec()
  19. {
  20. if (cpu_freq.QuadPart == 0)
  21. QueryPerformanceFrequency(&cpu_freq);
  22. return cpu_freq.QuadPart/1000000;
  23. }
  24. TOOLKIT_API cputime_t cputime_per_msec()
  25. {
  26. if (cpu_freq.QuadPart == 0)
  27. QueryPerformanceFrequency(&cpu_freq);
  28. return cpu_freq.QuadPart/1000;
  29. }
  30. TOOLKIT_API cputime_t cputime_per_sec()
  31. {
  32. if (cpu_freq.QuadPart == 0)
  33. QueryPerformanceFrequency(&cpu_freq);
  34. return cpu_freq.QuadPart;
  35. }
  36. TOOLKIT_API unsigned int cputime_as_usec(cputime_t tm)
  37. {
  38. if (cpu_freq.QuadPart == 0)
  39. QueryPerformanceFrequency(&cpu_freq);
  40. return (unsigned int)(tm*1000000/cpu_freq.QuadPart);
  41. }
  42. TOOLKIT_API unsigned int cputime_as_msec(cputime_t tm)
  43. {
  44. if (cpu_freq.QuadPart == 0)
  45. QueryPerformanceFrequency(&cpu_freq);
  46. return (unsigned int)(tm*1000/cpu_freq.QuadPart);
  47. }
  48. TOOLKIT_API unsigned int cputime_as_sec(cputime_t tm)
  49. {
  50. if (cpu_freq.QuadPart == 0)
  51. QueryPerformanceFrequency(&cpu_freq);
  52. return (unsigned int)(tm/cpu_freq.QuadPart);
  53. }
  54. TOOLKIT_API unsigned int cputime_usec(cputime_t tm)
  55. {
  56. if (cpu_freq.QuadPart == 0)
  57. QueryPerformanceFrequency(&cpu_freq);
  58. return (unsigned int)(tm*1000000%cpu_freq.QuadPart);
  59. }
  60. TOOLKIT_API unsigned int cputime_msec(cputime_t tm)
  61. {
  62. if (cpu_freq.QuadPart == 0)
  63. QueryPerformanceFrequency(&cpu_freq);
  64. return (unsigned int)(tm*1000%cpu_freq.QuadPart);
  65. }
  66. TOOLKIT_API unsigned int cputime_sec(cputime_t tm)
  67. {
  68. if (cpu_freq.QuadPart == 0)
  69. QueryPerformanceFrequency(&cpu_freq);
  70. return (unsigned int)(tm%cpu_freq.QuadPart);
  71. }
  72. TOOLKIT_API cputime_t cputime_advance_msec(cputime_t t, unsigned int val)
  73. {
  74. if (cpu_freq.QuadPart == 0)
  75. QueryPerformanceFrequency(&cpu_freq);
  76. return t + val*cpu_freq.QuadPart/1000;
  77. }
  78. TOOLKIT_API cputime_t cputime_advance_sec(cputime_t t, unsigned int val)
  79. {
  80. if (cpu_freq.QuadPart == 0)
  81. QueryPerformanceFrequency(&cpu_freq);
  82. return t + val*cpu_freq.QuadPart;
  83. }
  84. TOOLKIT_API cputime_t cputime_advance_uec(cputime_t t, unsigned int val)
  85. {
  86. if (cpu_freq.QuadPart == 0)
  87. QueryPerformanceFrequency(&cpu_freq);
  88. return t + val*cpu_freq.QuadPart/1000000;
  89. }
  90. TOOLKIT_API void mmtime_init(mmtime_t *inst, UINT resolution)
  91. {
  92. TIMECAPS tc;
  93. timeGetDevCaps(&tc, sizeof(TIMECAPS));
  94. inst->resolution = min(max(resolution, tc.wPeriodMin) ,tc.wPeriodMax);
  95. timeBeginPeriod(resolution);/* set time resolution */
  96. inst->last_tick.LowPart = timeGetTime();
  97. inst->last_tick.HighPart = 0;
  98. }
  99. TOOLKIT_API void mmtime_term(mmtime_t *inst)
  100. {
  101. timeEndPeriod(inst->resolution);
  102. }
  103. TOOLKIT_API void mmtime_now(mmtime_t *inst, LARGE_INTEGER *t)
  104. {
  105. t->HighPart = inst->last_tick.HighPart;
  106. t->LowPart = timeGetTime();
  107. if (t->QuadPart < inst->last_tick.QuadPart) {
  108. t->HighPart++;
  109. }
  110. inst->last_tick.LowPart = t->LowPart;
  111. inst->last_tick.HighPart = t->HighPart;
  112. }
  113. struct multimedia_timer {
  114. struct mmtime_t mmtime;
  115. LARGE_INTEGER tm_start;
  116. int interval_num;
  117. int interval_den;
  118. LARGE_INTEGER trigger_count;
  119. HANDLE evt; /* sync event object */
  120. DWORD own_thread; /* cannot be used cross thread's boundary */
  121. };
  122. TOOLKIT_API multimedia_timer *multimedia_timer_create(UINT resolution)
  123. {
  124. multimedia_timer *timer;
  125. if (resolution == 0)
  126. resolution = 1; /* default resolution */
  127. timer = MALLOC_T(multimedia_timer);
  128. if (timer) {
  129. timer->evt = CreateEvent(NULL, FALSE, FALSE, NULL);
  130. if (timer->evt) {
  131. timer->own_thread = GetCurrentThreadId();
  132. mmtime_init(&timer->mmtime, resolution);
  133. mmtime_now(&timer->mmtime, &timer->tm_start);
  134. } else {
  135. free(timer);
  136. timer = NULL;
  137. }
  138. }
  139. return timer;
  140. }
  141. TOOLKIT_API void multimedia_timer_destroy(multimedia_timer *timer)
  142. {
  143. if (timer) {
  144. mmtime_term(&timer->mmtime);
  145. free(timer);
  146. }
  147. }
  148. TOOLKIT_API UINT multimedia_timer_actual_resolution(multimedia_timer *timer)
  149. {
  150. return timer->mmtime.resolution;
  151. }
  152. TOOLKIT_API int multimedia_timer_sleep(multimedia_timer *timer, unsigned int delay)
  153. {
  154. if (!timer)
  155. return -1;
  156. assert(GetCurrentThreadId() == timer->own_thread);
  157. if (delay) {
  158. if (timeSetEvent(delay, timer->mmtime.resolution,
  159. (LPTIMECALLBACK)timer->evt, 0,
  160. TIME_CALLBACK_EVENT_SET|TIME_ONESHOT)) {
  161. WaitForSingleObject(timer->evt, INFINITE);
  162. }
  163. }
  164. return 0;
  165. }
  166. TOOLKIT_API int multimedia_timer_abort(multimedia_timer *timer)
  167. {
  168. if (!timer)
  169. return -1;
  170. SetEvent(timer->evt);
  171. return 0;
  172. }
  173. TOOLKIT_API int multimedia_timer_adaptive_sleep_init(multimedia_timer *timer, int interval_den, int interval_num)
  174. {
  175. int t;
  176. if (!timer || !interval_num || !interval_den)
  177. return -1;
  178. t = gcd(interval_den, interval_num);
  179. interval_num /= t;
  180. interval_den /= t;
  181. assert(GetCurrentThreadId() == timer->own_thread);
  182. mmtime_now(&timer->mmtime, &timer->tm_start);
  183. timer->interval_den = interval_den;
  184. timer->interval_num = interval_num;
  185. timer->trigger_count.QuadPart = 0;
  186. return 0;
  187. }
  188. TOOLKIT_API int multimedia_timer_adaptive_sleep(multimedia_timer *timer)
  189. {
  190. LARGE_INTEGER now;
  191. LARGE_INTEGER total;
  192. if (!timer)
  193. return -1;
  194. assert(GetCurrentThreadId() == timer->own_thread);
  195. mmtime_now(&timer->mmtime, &now);
  196. timer->trigger_count.QuadPart += 1;
  197. total.QuadPart = timer->tm_start.QuadPart + timer->trigger_count.QuadPart * 1000LL * timer->interval_num / timer->interval_den;
  198. if (now.QuadPart < total.QuadPart)
  199. multimedia_timer_sleep(timer, (unsigned int)(total.QuadPart - now.QuadPart));
  200. return 0;
  201. }
  202. /* example */
  203. /*
  204. static void print_time()
  205. {
  206. SYSTEMTIME st;
  207. GetLocalTime(&st);
  208. printf("[%04d-%02d-%02d %02d:%02d:%02d.%03d]\n", st.wYear, st.wMonth, st.wDay,
  209. st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
  210. }
  211. int main()
  212. {
  213. int i;
  214. multimedia_timer *timer = multimedia_timer_create(1);
  215. multimedia_timer_adaptive_sleep_init(timer, 90000, 3003);
  216. print_time();
  217. for (i = 0; i < 300; ++i) {
  218. multimedia_timer_adaptive_sleep(timer);
  219. //print_time();
  220. }
  221. print_time();
  222. getchar();
  223. multimedia_timer_destroy(timer);
  224. return 0;
  225. }
  226. */