/***************************************************************************
 *                                                                         *
 *   RTKICK.C                                                              *
 *                                                                         *
 *   Copyright (c) 1987-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This is the real-time kicktable handler, used to kick off a selected  *
 *   subroutine a specified number of seconds from the present time.       *
 *                                                                         *
 *                                            - T. Stryker 6/24/86         *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "phasedbg.h"

#define FILREV "$Revision: 5 $"

#define   INCSIZ    20             /* increment size for expanding kcktbl  */

INT rtkoff=0;                      /* 1=turn off all RTKICK calls 0=on     */

static
struct kook {                      /* kicktable entry layout               */
     INT countr;                   /*   number of seconds yet to go        */
     VOID (*dest)();               /*   subroutine address to invoke       */
} *kcktbl;

static INT ktsize=0;               /* size of in-memory rtkick table       */

static VOID incrtk(VOID);          /* inc the size of kcktbl by INCSIZ     */

VOID
rtkick(                            /* real-time kicktable handler          */
INT delay,                         /*   time to delay between calls        */
VOID (*dstrou)(VOID))              /*   routine to call after delays       */
{
     INT i;
     struct kook *kckptr;

     for (i=0,kckptr=kcktbl ; i < ktsize ; i++,kckptr++) {
          if (kckptr->countr == 0) {
               kckptr->countr=delay;
               kckptr->dest=dstrou;
               return;
          }
     }
     incrtk();
     kcktbl[i].countr=delay;
     kcktbl[i].dest=dstrou;
}

VOID
prcrtk(VOID)                       /* call an rtkick's specified routine   */
{
     INT i;
     typedef VOID (*RTKICK_ROUT)(VOID);

     for (i=0 ; i < ktsize ; i++) {
          if (rtkoff) {
               return;
          }
          if (kcktbl[i].countr != 0 && --(kcktbl[i].countr) == 0) {
               clingo=0;
               clrprf();
               BEG_PHASE("Real-time kick",kcktbl[i].dest);
               (*((RTKICK_ROUT)kcktbl[i].dest))();
               END_PHASE("Real-time kick",i);
          }
     }
}

static VOID
incrtk(VOID)                       /* inc the size of kcktbl by INCSIZ     */
{
     if (ktsize == 0) {
          kcktbl=(struct kook *)alcmem(INCSIZ*sizeof(struct kook));
     }
     else {
          kcktbl=(struct kook *)alcrsz(kcktbl,ktsize*sizeof(struct kook),
                                       (ktsize+INCSIZ)*sizeof(struct kook));
     }
     setmem(&kcktbl[ktsize],sizeof(struct kook)*INCSIZ,0);
     ktsize+=INCSIZ;
}
