home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / PCTV3N2.ZIP / TIMEOUTS.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-03-29  |  6.8 KB  |  201 lines

  1. UNIT TimeOuts; { TIMEOUTS.PAS -- Deadman timers for applications }
  2. INTERFACE
  3. USES Dos;
  4. CONST
  5.   TimerIntLvl  = $1C; {------------------ Timer Interrupt level }
  6.   MaxTimeOuts  = 8;   {---------------------- Default "maximum" }
  7.  
  8. TYPE
  9.   PTimerRec = ^TTimerRec;
  10.   TTimerRec = RECORD  {------------ A TimeOut timer data record }
  11.     TimerAsn : Boolean;                { TRUE if timer assigned }
  12.     TimerAct : Boolean;                  { TRUE if timer active }
  13.     TimedOut : Boolean;               { TRUE if timer timed out }
  14.     TimeBase : LongInt;      { User-specified time-out (counts) }
  15.     TimerCnt : LongInt;               { Current downcount value }
  16.   END;
  17.  
  18.   PTimerData = ^TTimerData; {---- Default data array for timers }
  19.   TTimerData = ARRAY[1..MaxTimeOuts] OF TTimerRec;
  20.  
  21.   PTimer = ^TTimer;
  22.   TTimer = OBJECT {-------------------------- The TTimer object }
  23.     Timers    : Integer;         { Number of timers used by app }
  24.     TimerData : PTimerData;       { Pointer to array of records }
  25.     CONSTRUCTOR Init(NTimers : Integer);
  26.     DESTRUCTOR  Done;
  27.     PROCEDURE   GetTimer(VAR TN : Integer);    { TN = Timer no. }
  28.     PROCEDURE   SetTimer(TN : Integer; TSecs : LongInt);
  29.     PROCEDURE   StartTimer(TN : Integer);
  30.     PROCEDURE   StopTimer(TN : Integer);
  31.     PROCEDURE   FreeTimer(TN : Integer);
  32.     FUNCTION    IsTimedOut(TN : Integer): Boolean;
  33.     FUNCTION    TimerActive(TN : Integer): Boolean;
  34.     PROCEDURE   ProcessInt;
  35.   END;
  36.  
  37. IMPLEMENTATION
  38.  
  39. VAR
  40.   TimerIntSave : Pointer; {------------ Original INT 1CH vector }
  41.   TheTimer     : PTimer;            { ISR link to TTimer object }
  42.  
  43. PROCEDURE TimISR(Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP: Word);
  44.                                                        INTERRUPT;
  45. {----------------------------------------------------------------
  46.  This is the INT 1CH Interrupt Servicing Routine.  Since
  47.  an interrupt processor cannot be an object method, this
  48.  routine does nothing more that invoke the TTImer.ProcessInt
  49.  routine.  It uses the "TheTimer" pointer to address the
  50.  TTimer object.
  51. ----------------------------------------------------------------}
  52. VAR I : Integer;
  53. BEGIN
  54.   TheTimer^.ProcessInt;
  55. END;
  56.  
  57. CONSTRUCTOR TTimer.Init(NTimers : Integer);
  58. {----------------------------------------------------------------
  59.   Instantiates the TTimer object for "NTimers" timers, allocates
  60.   heap space for the data fields, and sets up the interrupt vector.
  61. ----------------------------------------------------------------}
  62. VAR I : Integer;
  63.  
  64. BEGIN
  65.   Timers := NTimers;        { Save the number of timers desired }
  66.   GetMem(TimerData,(Timers * SizeOf(TTimerData)));
  67.   FOR I := 1 TO Timers DO FreeTimer(I); { Initialize the timers }
  68.   TheTimer := @Self;                 { Set up the ISR's pointer }
  69.   GetIntVec(TimerIntLvl, TimerIntSave); { Set up the ISR vector }
  70.   SetIntVec(TimerIntLvl, @TimISR);
  71. END;
  72.  
  73. DESTRUCTOR TTimer.Done;
  74. {----------------------------------------------------------------
  75.  Disposes of the TTimer instance and resets the timer interrupt.
  76. ----------------------------------------------------------------}
  77. BEGIN
  78.   SetIntVec(TimerIntLvl, TimerIntSave); { Restore the ISR vector }
  79.   FreeMem(TimerData,(Timers * SizeOf(TTimerData)));
  80. END;
  81.  
  82. PROCEDURE TTimer.GetTimer(VAR TN : Integer);
  83. {----------------------------------------------------------------
  84.  Assigns the next free timer (if any) to the caller.  (Returns
  85.  "TN" set to zero if none are available.)
  86. ----------------------------------------------------------------}
  87. VAR I : Integer;
  88.  
  89. BEGIN
  90.   TN := 0;
  91.   FOR I := 1 TO Timers DO BEGIN
  92.     WITH TimerData^[I] DO BEGIN
  93.       IF (NOT TimerAsn) THEN BEGIN
  94.         FreeTimer(I);
  95.         TimerAsn := TRUE;
  96.         TN := I;
  97.         Exit
  98.       END;
  99.     END;
  100.   END;
  101. END;
  102.  
  103. PROCEDURE TTimer.SetTimer(TN : Integer; TSecs : LongInt);
  104. {----------------------------------------------------------------
  105.  Sets up (but does not start) the assigned timer with the caller-
  106.  specified down-count, in SECONDS.
  107. ----------------------------------------------------------------}
  108. BEGIN
  109.   WITH TimerData^[TN] DO BEGIN
  110.     IF (TimerAsn AND (TSecs > 0)) THEN BEGIN
  111.       TimeBase := TSecs * (1193180 DIV 65536);   { TSecs * 18.2 }
  112.       TimerCnt := 0;
  113.     END;
  114.   END;
  115. END;
  116.  
  117. PROCEDURE TTimer.StartTimer(TN : Integer);
  118. {----------------------------------------------------------------
  119.  Starts the down-count operation for Timer "TN" (if assigned).
  120. ----------------------------------------------------------------}
  121. BEGIN
  122.   WITH TimerData^[TN] DO BEGIN
  123.     IF (TimerAsn) THEN BEGIN
  124.       TimedOut := FALSE;
  125.       TimerAct := TRUE;
  126.       TimerCnt := TimeBase;
  127.     END;
  128.   END;
  129. END;
  130.  
  131. PROCEDURE TTimer.StopTimer(TN : Integer);
  132. {----------------------------------------------------------------
  133.  Stops the down-count operation for Timer "TN" (while running).
  134. ----------------------------------------------------------------}
  135. BEGIN
  136.   WITH TimerData^[TN] DO BEGIN
  137.     IF (TimerAsn) THEN BEGIN
  138.       TimerAct := FALSE;
  139.       TimerCnt := 0;
  140.     END;
  141.   END;
  142. END;
  143.  
  144. PROCEDURE TTimer.FreeTimer(TN : Integer);
  145. {----------------------------------------------------------------
  146.  "Unassigns" Timer "TN" and intializes the data fields.
  147. ----------------------------------------------------------------}
  148. BEGIN
  149.   WITH TimerData^[TN] DO BEGIN
  150.     TimerAsn := FALSE;
  151.     TimerAct := FALSE;
  152.     TimedOut := FALSE;
  153.     TimeBase := 0;
  154.     TimerCnt := 0;
  155.   END;
  156. END;
  157.  
  158. FUNCTION TTimer.IsTimedOut(TN : Integer): Boolean;
  159. {----------------------------------------------------------------
  160.  Returns TRUE if timer "TN" has timed out; then, reset TimedOut.
  161. ----------------------------------------------------------------}
  162. BEGIN
  163.   WITH TimerData^[TN] DO BEGIN
  164.     IF (TimerAsn AND TimerAct AND TimedOut) THEN IsTimedOut := TRUE
  165.     ELSE IsTimedOut := FALSE;
  166.     TimedOut := FALSE;
  167.   END;
  168. END;
  169.  
  170. FUNCTION TTimer.TimerActive(TN : Integer): Boolean;
  171. {----------------------------------------------------------------
  172.  Returns TRUE if timer "TN" is active.
  173. ----------------------------------------------------------------}
  174. BEGIN
  175.   WITH TimerData^[TN] DO BEGIN
  176.     IF (TimerAsn AND TimerAct) THEN TimerActive := TRUE
  177.     ELSE TimerActive := FALSE;
  178.   END;
  179. END;
  180.  
  181. PROCEDURE TTimer.ProcessInt;
  182. {----------------------------------------------------------------
  183.  This logic does the actual processing of the timer interrupt.
  184.  It decrements all active timers that have positive values.
  185.  If the decremented value reaches zero, the timer is set to
  186.  "Timed Out."
  187. ----------------------------------------------------------------}
  188. VAR TN : Integer;
  189.  
  190. BEGIN
  191.   FOR TN := 1 TO Timers DO BEGIN
  192.     WITH TimerData^[TN] DO BEGIN
  193.       IF (TimerAsn AND TimerAct AND (TimerCnt > 0)) THEN BEGIN
  194.         Dec(TimerCnt);
  195.         IF (TimerCnt = 0) THEN TimedOut := TRUE;
  196.       END;
  197.     END;
  198.   END;
  199. END;
  200. END.
  201.