periodic.c 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. #include "stdinc.h"
  2. #include "dat.h"
  3. #include "fns.h"
  4. #include "error.h"
  5. struct Periodic {
  6. VtLock *lk;
  7. int die;
  8. void (*f)(void*);
  9. void *a;
  10. int msec;
  11. };
  12. static void periodicThread(void *a);
  13. Periodic *
  14. periodicAlloc(void (*f)(void*), void *a, int msec)
  15. {
  16. Periodic *p;
  17. p = vtMemAllocZ(sizeof(Periodic));
  18. p->lk = vtLockAlloc();
  19. p->f = f;
  20. p->a = a;
  21. p->msec = msec;
  22. if(p->msec < 10)
  23. p->msec = 10;
  24. vtThread(periodicThread, p);
  25. return p;
  26. }
  27. void
  28. periodicKill(Periodic *p)
  29. {
  30. if(p == nil)
  31. return;
  32. vtLock(p->lk);
  33. p->die = 1;
  34. vtUnlock(p->lk);
  35. }
  36. static void
  37. periodicFree(Periodic *p)
  38. {
  39. vtLockFree(p->lk);
  40. vtMemFree(p);
  41. }
  42. static void
  43. periodicThread(void *a)
  44. {
  45. Periodic *p = a;
  46. double t, ct, ts;
  47. vtThreadSetName("periodic");
  48. ct = nsec()*1e-6;
  49. t = ct + p->msec;
  50. for(;;){
  51. /* skip missed */
  52. while(t <= ct)
  53. t += p->msec;
  54. ts = t - ct;
  55. if(ts > 1000)
  56. ts = 1000;
  57. sleep(ts);
  58. ct = nsec()*1e-6;
  59. vtLock(p->lk);
  60. if(p->die){
  61. vtUnlock(p->lk);
  62. break;
  63. }
  64. if(t <= ct){
  65. p->f(p->a);
  66. t += p->msec;
  67. }
  68. vtUnlock(p->lk);
  69. }
  70. periodicFree(p);
  71. }