home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / stdwin / Ports / x11 / amtimer.c next >
Encoding:
C/C++ Source or Header  |  1991-04-03  |  3.6 KB  |  158 lines  |  [TEXT/????]

  1. /* Amoeba-specific timer code. */
  2.  
  3. #include "x11.h"
  4.  
  5. #include <amoeba.h>
  6. #include <semaphore.h>
  7.  
  8. interval sys_milli();
  9.  
  10. /* Although win->timer and the second parameter of wsettimer() are in
  11.    deciseconds, *all* other values are in milliseconds. */
  12.  
  13. static interval nexttimer;
  14.  
  15. /* Compute a new value for nexttimer.
  16.    This is the system time (in msec.) when the first event should go
  17.    off, or 0 if there are no scheduled timer events.
  18.    Return the relevant window as a convenience. */
  19.  
  20. static WINDOW *
  21. setnexttimer()
  22. {
  23.     WINDOW *win = _wnexttimer();
  24.     
  25.     if (win == NULL)
  26.         nexttimer = 0;
  27.     else
  28.         nexttimer = win->timer * 100;
  29.     _wdebug(4, "setnexttimer: nexttimer at %d for %x", nexttimer, win);
  30.     return win;
  31. }
  32.  
  33. /* Set the timer for a given window at now + deciseconds;
  34.    or discard the timer if deciseconds is zero. */
  35.  
  36. void
  37. wsettimer(win, deciseconds)
  38.     WINDOW *win;
  39.     int deciseconds;
  40. {
  41.     _wdebug(3, "wsettimer: deciseconds=%d", deciseconds);
  42.     win->timer = 0;
  43.     if (deciseconds > 0)
  44.         win->timer = deciseconds + sys_milli() / 100;
  45.     _wdebug(3, "wsettimer(%d): timer set to %d", deciseconds, win->timer);
  46.     (void) setnexttimer();
  47. }
  48.  
  49. /* Return an interval until the next timer, or -1 if no timers.
  50.    This is suitable to pass directly to mu_trylock() etc. */
  51.  
  52. interval
  53. nextdelay()
  54. {
  55.     interval now;
  56.     
  57.     if (nexttimer == 0)
  58.         return -1; /* No timer events */
  59.     now = sys_milli();
  60.     if (nexttimer <= now)
  61.         return 0; /* Immediate timer event */
  62.     return nexttimer - now; /* Milliseconds until timer event */
  63. }
  64.  
  65. /* Check if a timer has gone off, and if so, generate an appropriate event.
  66.    This can be called at any time, but for efficiency reasons it should
  67.    only be called when an alarm has actually gone off.
  68.    If an alarm has gone off, it will always be found by this function. */
  69.  
  70. static bool
  71. dotimer(ep)
  72.     EVENT *ep;
  73. {
  74.     WINDOW *win;
  75.     interval next;
  76.     
  77.     win = setnexttimer();
  78.     if (win == NULL) {
  79.         _wdebug(1, "dotimer: no event found (spurious call)");
  80.         return FALSE;
  81.     }
  82.     next = nextdelay();
  83.     if (next < 0) {
  84.         /* Shouldn't happen -- setnexttimer should have been NULL */
  85.         _wdebug(0, "dotimer: nextdelay() < 0 ???");
  86.         return FALSE;
  87.     }
  88.     if (next == 0) {
  89.         _wdebug(3, "dotimer: reporting timer event");
  90.         ep->type = WE_TIMER;
  91.         ep->window = win;
  92.         win->timer = 0;
  93.         (void) setnexttimer();
  94.         return TRUE;
  95.     }
  96.     else {
  97.         _wdebug(1, "dotimer: it is not yet time");
  98.         return FALSE;
  99.     }
  100. }
  101.  
  102. /* Check for timer events, return TRUE if one found.
  103.    If a timer event is due now, return it immediately.
  104.    Otherwise, if mayblock is FALSE, return FALSE immediately.
  105.    Otherwise, block until either an X event is available or the next
  106.    timer event happens (in which case it is returned).
  107. */
  108.  
  109. bool
  110. _w_checktimer(ep, mayblock)
  111.     EVENT *ep;
  112.     bool mayblock;
  113. {
  114.     for (;;) {
  115.         interval delay;
  116.         int status;
  117.         
  118.         delay = nextdelay();
  119.         if (delay == 0) {
  120.             if (dotimer(ep))
  121.                 return TRUE;
  122.         }
  123.         if (!mayblock)
  124.             return FALSE;
  125.         /* Block until next X event or next timer event */
  126.         status = XamBlock(_wd, delay);
  127.         _wdebug(4, "_w_checktimer: status %d", status);
  128.         if (status > 0) {
  129.             _wdebug(3, "_w_checktimer: external event, status %d",
  130.                                 status);
  131.             ep->type = WE_EXTERN;
  132.             ep->window = NULL;
  133.             ep->u.command = status;
  134.             return TRUE;
  135.         }
  136.         if (status == 0) {
  137.             _wdebug(3, "_w_checktimer: X event");
  138.             return FALSE;
  139.         }
  140.         _wdebug(3, "_w_checktimer: timer went off");
  141.         /* Negative return means timer went off
  142.            (or interrupted system call) */
  143.     }
  144. }
  145.  
  146. semaphore *_wsema; /* Global, used by winit() */
  147.  
  148. /* Interface to specify the semaphore used by XamBlock().
  149.    *** This must be called before calling winit[new]() !!! ***
  150.    */
  151.  
  152. void
  153. wsetsema(ps)
  154.     semaphore *ps;
  155. {
  156.     _wsema = ps;
  157. }
  158.