home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / fax-3.2.1 / lib / libutil / alarm.c next >
Encoding:
C/C++ Source or Header  |  1992-07-31  |  3.0 KB  |  155 lines

  1. /*
  2.   This file is part of the NetFax system.
  3.  
  4.   (c) Copyright 1989 by David M. Siegel and Sundar Narasimhan.
  5.       All rights reserved.
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation.
  10.  
  11.     This program is distributed in the hope that it will be useful, 
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of 
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <signal.h>
  23. #include <sys/time.h>
  24.  
  25. #include "alloc.h"
  26. #include "list.h"
  27. #include "alarm.h"
  28.  
  29. #define ALARM_GRANULARITY 200            /* in msecs */
  30.  
  31. static int granularity = ALARM_GRANULARITY;
  32.  
  33. typedef struct _alarm_event {
  34.     int rate;
  35.     int count;
  36.     int (*routine)();
  37.     char *data;
  38. } alarm_event;
  39.  
  40. static LIST *event_list = NULL;
  41.  
  42. int
  43. alarm_add_event(routine, interval, data)
  44. int (*routine)();
  45. float interval;
  46. char *data;
  47. {
  48.     alarm_event *event;
  49.     int cfree();
  50.  
  51.     if ((event = salloc(1, alarm_event)) == NULL)
  52.       return (-1);
  53.  
  54.     /* setup event info */
  55.     event->rate = (int)((interval * 1000) / granularity);
  56.     event->routine = routine;
  57.     event->data = data;
  58.  
  59.     if (event_list == NULL)
  60.       event_list = list_make(NULL, cfree);
  61.  
  62.     /* append to list of all alarms */
  63.     list_add(event_list, (char *)event);
  64.  
  65.     return (0);
  66. }
  67.  
  68. static alarm_event *
  69. find_routine(event, routine)
  70. alarm_event *event;
  71. int (*routine)();
  72. {
  73.     if (event->routine == routine)
  74.       return (event);
  75.     else
  76.       return (NULL);
  77. }
  78.  
  79. int
  80. alarm_delete_event(routine)
  81. int (*routine)();
  82. {
  83.     alarm_event *event;
  84.  
  85.     /* find event for the routine */
  86.     event = (alarm_event *)list_map(event_list, find_routine, routine);
  87.  
  88.     if (event == NULL)
  89.       return (-1);
  90.  
  91.     list_delete(event_list, (char *)event);
  92.  
  93.     return (0);
  94. }
  95.  
  96. static int
  97. do_update(event)
  98. alarm_event *event;
  99. {
  100.     ++(event->count);
  101.  
  102.     /* run event when rate count exceeded */
  103.     if (event->count >= event->rate) {
  104.  
  105.     /* reset the rate counter */
  106.     event->count = 0;
  107.  
  108.     /* run the event */
  109.     (*event->routine)(event->data, event->rate);
  110.     }
  111.  
  112.     return (0);
  113. }
  114.  
  115. static
  116. alarm_handler()
  117. {
  118.     /* update and run each event */
  119.     list_map(event_list, do_update);
  120. }
  121.  
  122. int
  123. alarm_block()
  124. {
  125.     return (sigblock(sigmask(SIGALRM)));
  126. }
  127.  
  128. int
  129. alarm_restore(mask)
  130. int mask;
  131. {
  132.     return (sigsetmask(mask));
  133. }
  134.  
  135. int
  136. alarm_start()
  137. {
  138.     struct itimerval value;
  139.  
  140.     if (event_list == NULL)
  141.       event_list = list_make(NULL, cfree);
  142.  
  143.     /*SUPPRESS 544*/
  144.     if (signal(SIGALRM, alarm_handler) < 0)
  145.       return (-1);
  146.  
  147.     value.it_value.tv_sec  = value.it_interval.tv_sec  = 0;
  148.     value.it_value.tv_usec = value.it_interval.tv_usec = granularity*1000;
  149.  
  150.     if (setitimer(ITIMER_REAL, &value, NULL) < 0)
  151.       return (-1);
  152.  
  153.     return (0);
  154. }
  155.