cputime.c 6.0 KB

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