egg_timer.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include <stdio.h> /* For NULL */
  2. #include <sys/time.h> /* For gettimeofday() */
  3. #include "common.h"
  4. #include "egg_timer.h"
  5. /* Internal use only. */
  6. typedef struct egg_timer_b {
  7. struct egg_timer_b *next;
  8. int id;
  9. Function callback;
  10. void *client_data;
  11. egg_timeval_t howlong;
  12. egg_timeval_t trigger_time;
  13. int flags;
  14. } egg_timer_t;
  15. /* We keep a sorted list of active timers. */
  16. static egg_timer_t *timer_list_head = NULL;
  17. static unsigned int timer_next_id = 1;
  18. /* Based on TclpGetTime from Tcl 8.3.3 */
  19. int timer_get_time(egg_timeval_t *curtime)
  20. {
  21. struct timeval tv;
  22. struct timezone tz;
  23. (void) gettimeofday(&tv, &tz);
  24. curtime->sec = tv.tv_sec;
  25. curtime->usec = tv.tv_usec;
  26. return(0);
  27. }
  28. int timer_create_complex(egg_timeval_t *howlong, Function callback, void *client_data, int flags)
  29. {
  30. egg_timer_t *timer, *prev;
  31. egg_timeval_t trigger_time;
  32. timer_get_time(&trigger_time);
  33. trigger_time.sec += howlong->sec;
  34. trigger_time.usec += howlong->usec;
  35. /* Find out where this should go in the list. */
  36. prev = NULL;
  37. for (timer = timer_list_head; timer; timer = timer->next) {
  38. if (trigger_time.sec < timer->trigger_time.sec) break;
  39. if (trigger_time.sec == timer->trigger_time.sec && trigger_time.usec < timer->trigger_time.usec) break;
  40. prev = timer;
  41. }
  42. /* Fill out a new timer. */
  43. timer = (egg_timer_t *)malloc(sizeof(*timer));
  44. timer->callback = callback;
  45. timer->client_data = client_data;
  46. timer->flags = flags;
  47. egg_memcpy(&timer->howlong, howlong, sizeof(*howlong));
  48. egg_memcpy(&timer->trigger_time, &trigger_time, sizeof(trigger_time));
  49. timer->id = timer_next_id++;
  50. /* Insert into timer list. */
  51. if (prev) {
  52. timer->next = prev->next;
  53. prev->next = timer;
  54. }
  55. else {
  56. timer->next = timer_list_head;
  57. timer_list_head = timer;
  58. }
  59. if (timer_next_id == 0) timer_next_id++;
  60. return(timer->id);
  61. }
  62. /* Destroy a timer, given an id. */
  63. int timer_destroy(int timer_id)
  64. {
  65. egg_timer_t *prev, *timer;
  66. prev = NULL;
  67. for (timer = timer_list_head; timer; timer = timer->next) {
  68. if (timer->id == timer_id) break;
  69. }
  70. if (!timer) return(1); /* Not found! */
  71. /* Unlink it. */
  72. if (prev) prev->next = timer->next;
  73. else timer_list_head = timer->next;
  74. free(timer);
  75. return(0);
  76. }
  77. int timer_destroy_all()
  78. {
  79. egg_timer_t *timer;
  80. for (timer = timer_list_head; timer; timer = timer->next) {
  81. free(timer);
  82. }
  83. timer_list_head = NULL;
  84. return(0);
  85. }
  86. int timer_get_shortest(egg_timeval_t *howlong)
  87. {
  88. egg_timeval_t curtime;
  89. egg_timer_t *timer = timer_list_head;
  90. /* No timers? Boo. */
  91. if (!timer) return(1);
  92. timer_get_time(&curtime);
  93. if (timer->trigger_time.sec <= curtime.sec) howlong->sec = 0;
  94. else howlong->sec = timer->trigger_time.sec - curtime.sec;
  95. if (timer->trigger_time.usec <= curtime.usec) howlong->usec = 0;
  96. else howlong->usec = timer->trigger_time.usec - curtime.usec;
  97. return(0);
  98. }
  99. int timer_run()
  100. {
  101. egg_timeval_t curtime;
  102. egg_timer_t *timer;
  103. Function callback;
  104. void *client_data;
  105. while ((timer = timer_list_head)) {
  106. timer_get_time(&curtime);
  107. if (timer->trigger_time.sec > curtime.sec || (timer->trigger_time.sec == curtime.sec && timer->trigger_time.usec > curtime.usec)) break;
  108. timer_list_head = timer_list_head->next;
  109. callback = timer->callback;
  110. client_data = timer->client_data;
  111. if (timer->flags & TIMER_REPEAT) {
  112. egg_timer_t *prev, *tptr;
  113. /* Update timer. */
  114. timer->trigger_time.sec += timer->howlong.sec;
  115. timer->trigger_time.usec += timer->howlong.usec;
  116. prev = NULL;
  117. for (tptr = timer_list_head; tptr; tptr = tptr->next) {
  118. if (tptr->trigger_time.sec > timer->trigger_time.sec || (tptr->trigger_time.sec == timer->trigger_time.sec && tptr->trigger_time.usec > timer->trigger_time.usec)) break;
  119. prev = tptr;
  120. }
  121. if (prev) {
  122. timer->next = prev->next;
  123. prev->next = timer;
  124. }
  125. else {
  126. timer->next = timer_list_head;
  127. timer_list_head = timer;
  128. }
  129. }
  130. else {
  131. free(timer);
  132. }
  133. callback(client_data);
  134. }
  135. return(0);
  136. }