Subversion Repositories Kolibri OS

Rev

Rev 4364 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
  3.  *
  4.  * This file is part of NetSurf, http://www.netsurf-browser.org/
  5.  *
  6.  * NetSurf is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; version 2 of the License.
  9.  *
  10.  * NetSurf is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17.  */
  18.  
  19. #include <sys/time.h>
  20. #include <time.h>
  21. #include <stdlib.h>
  22.  
  23. #include "utils/schedule.h"
  24. #include "framebuffer/schedule.h"
  25.  
  26. #include "utils/log.h"
  27.  
  28. /* linked list of scheduled callbacks */
  29. static struct nscallback *schedule_list = NULL;
  30.  
  31. /**
  32.  * scheduled callback.
  33.  */
  34. struct nscallback
  35. {
  36.         struct nscallback *next;
  37.         struct timeval tv;
  38.         void (*callback)(void *p);
  39.         void *p;
  40. };
  41.  
  42.  
  43. /**
  44.  * Schedule a callback.
  45.  *
  46.  * \param  tival     interval before the callback should be made / cs
  47.  * \param  callback  callback function
  48.  * \param  p         user parameter, passed to callback function
  49.  *
  50.  * The callback function will be called as soon as possible after t cs have
  51.  * passed.
  52.  */
  53.  
  54. void schedule(int cs_ival, void (*callback)(void *p), void *p)
  55. {
  56.         struct nscallback *nscb;
  57.         struct timeval tv;
  58.  
  59.         tv.tv_sec = cs_ival / 100; /* cs to seconds */
  60.         tv.tv_usec = (cs_ival % 100) * 10000; /* remainder to microseconds */
  61.  
  62.         nscb = calloc(1, sizeof(struct nscallback));
  63.  
  64.         gettimeofday(&nscb->tv, NULL);
  65.         timeradd(&nscb->tv, &tv, &nscb->tv);
  66.  
  67.         nscb->callback = callback;
  68.         nscb->p = p;
  69.  
  70.         /* add to list front */
  71.         nscb->next = schedule_list;
  72.         schedule_list = nscb;
  73. }
  74.  
  75. /**
  76.  * Unschedule a callback.
  77.  *
  78.  * \param  callback  callback function
  79.  * \param  p         user parameter, passed to callback function
  80.  *
  81.  * All scheduled callbacks matching both callback and p are removed.
  82.  */
  83.  
  84. void schedule_remove(void (*callback)(void *p), void *p)
  85. {
  86.         struct nscallback *cur_nscb;
  87.         struct nscallback *prev_nscb;
  88.         struct nscallback *unlnk_nscb;
  89.  
  90.         if (schedule_list == NULL)
  91.                 return;
  92.  
  93.         LOG(("removing %p, %p", callback, p));
  94.  
  95.         cur_nscb = schedule_list;
  96.         prev_nscb = NULL;
  97.  
  98.         while (cur_nscb != NULL) {
  99.                 if ((cur_nscb->callback ==  callback) &&
  100.                     (cur_nscb->p ==  p)) {
  101.                         /* item to remove */
  102.  
  103.                         LOG(("callback entry %p removing  %p(%p)",
  104.                              cur_nscb, cur_nscb->callback, cur_nscb->p));
  105.  
  106.                         /* remove callback */
  107.                         unlnk_nscb = cur_nscb;
  108.                         cur_nscb = unlnk_nscb->next;
  109.  
  110.                         if (prev_nscb == NULL) {
  111.                                 schedule_list = cur_nscb;
  112.                         } else {
  113.                                 prev_nscb->next = cur_nscb;
  114.                         }
  115.                         free (unlnk_nscb);
  116.                 } else {
  117.                         /* move to next element */
  118.                         prev_nscb = cur_nscb;
  119.                         cur_nscb = prev_nscb->next;
  120.                 }
  121.         }
  122. }
  123.  
  124. /**
  125.  * Process scheduled callbacks up to current time.
  126.  *
  127.  * @return The number of milliseconds untill the next scheduled event
  128.  * or -1 for no event.
  129.  */
  130. int
  131. schedule_run(void)
  132. {
  133.         struct timeval tv;
  134.         struct timeval nexttime;
  135.         struct timeval rettime;
  136.         struct nscallback *cur_nscb;
  137.         struct nscallback *prev_nscb;
  138.         struct nscallback *unlnk_nscb;
  139.  
  140.         if (schedule_list == NULL)
  141.                 return -1;
  142.  
  143.         /* reset enumeration to the start of the list */
  144.         cur_nscb = schedule_list;
  145.         prev_nscb = NULL;
  146.         nexttime = cur_nscb->tv;
  147.  
  148.         gettimeofday(&tv, NULL);
  149.  
  150.         while (cur_nscb != NULL) {
  151.                 if (timercmp(&tv, &cur_nscb->tv, 0)) {
  152.                         /* scheduled time */
  153.  
  154.                         /* remove callback */
  155.                         unlnk_nscb = cur_nscb;
  156.  
  157.                         if (prev_nscb == NULL) {
  158.                                 schedule_list = unlnk_nscb->next;
  159.                         } else {
  160.                                 prev_nscb->next = unlnk_nscb->next;
  161.                         }
  162.  
  163.                         unlnk_nscb->callback(unlnk_nscb->p);
  164.  
  165.                         free(unlnk_nscb);
  166.                        
  167.                         /* need to deal with callback modifying the list. */
  168.                         if (schedule_list == NULL)
  169.                                 return -1; /* no more callbacks scheduled */
  170.                        
  171.                         /* reset enumeration to the start of the list */
  172.                         cur_nscb = schedule_list;
  173.                         prev_nscb = NULL;
  174.                         nexttime = cur_nscb->tv;
  175.                 } else {
  176.                         /* if the time to the event is sooner than the
  177.                          * currently recorded soonest event record it
  178.                          */
  179.                         if (timercmp(&nexttime, &cur_nscb->tv, 0)) {
  180.                                 nexttime = cur_nscb->tv;
  181.                         }
  182.                         /* move to next element */
  183.                         prev_nscb = cur_nscb;
  184.                         cur_nscb = prev_nscb->next;
  185.                 }
  186.         }
  187.  
  188.         /* make rettime relative to now */
  189.         timersub(&nexttime, &tv, &rettime);
  190.  
  191.         /*LOG(("returning time to next event as %ldms",(rettime.tv_sec * 1000) + (rettime.tv_usec / 1000))); */
  192.         /* return next event time in milliseconds (24days max wait) */
  193.         return (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000);
  194. }
  195.  
  196. void list_schedule(void)
  197. {
  198.         struct timeval tv;
  199.         struct nscallback *cur_nscb;
  200.  
  201.         gettimeofday(&tv, NULL);
  202.  
  203.         LOG(("schedule list at %ld:%ld", tv.tv_sec, tv.tv_usec));
  204.  
  205.         cur_nscb = schedule_list;
  206.  
  207.         while (cur_nscb != NULL) {
  208.                 LOG(("Schedule %p at %ld:%ld",
  209.                      cur_nscb, cur_nscb->tv.tv_sec, cur_nscb->tv.tv_usec));
  210.                 cur_nscb = cur_nscb->next;
  211.         }
  212. }
  213.  
  214.  
  215. /*
  216.  * Local Variables:
  217.  * c-basic-offset:8
  218.  * End:
  219.  */
  220.