/************************************************************************** 
   AES.C 
*************************************************************************** 
  This module shows how to schedule an AES process. It demonstrates a 
  simple AES procedure that reschedules itself, setting up the AES  
  process structure, and scheduling and cancelling the AES procedure. 
*************************************************************************/ 
#include <stdio.h> 
#include <nwadv.h> 

#define  COUNT_START   0 
#define  COUNT_END     10 
#define  COUNT_INC     1 
#define  DELAY         18 

/* Globals */ 

LONG   GlobalCount = COUNT_START; 
struct MyAESProcessStructure mainAESProcess; 
LONG   mainAESResourceTag, myCount;  

/************************************************************************** 
   This is a customized version of the AESProcessStructure found in the   
   nwthread.h header file.  A single field has been added to demonstrate  
   how information may be passed to the AES procedure when it is called.  
   It is not necessary to redefine this structure if no user specific     
   information is to be passed to the AES procedure.  In this case, using 
   the structure defined in the nwthread.h header file is sufficient.     
*************************************************************************/
struct   MyAESProcessStructure 
{
   struct AESProcessStructure *ALink;  /* Set by AES */
   LONG   AWakeUpDelayAmount;          /* # ticks to wait; unchanged */
   LONG   AWakeUpTime;                 /* Set by AES */
   void   (*AProcessToCall)(void *);   /* function to call; unchanged */
   LONG   ARTag;                       /* Set to resource tag; unchanged */
   LONG   AOldLink;                    /* Set to NULL */
   LONG   myValue;                     /* addition to standard structure */
};  

/************************************************************************** 
   This is the actual procedure that will be scheduled with the AES     
   function.  It simply sets a global value, increments the custom      
   field added to the AESProcessStructure, and then reschedules itself. 
   The DELAY constant of 18 will cause the procedure to execute         
   approximately every second.  Although it is not demonstrated in this 
   example, it is legal for this procedure to go to sleep because it    
   is scheduled with the sleep version of the AES functions.            
*************************************************************************/
void MyEventProcedure(struct MyAESProcessStructure *myAESProcessP) 
{
   myAESProcessP->myValue += COUNT_INC; 
   GlobalCount = myAESProcessP->myValue; 

   ScheduleSleepAESProcessEvent((
                                struct AESProcessStructure *)myAESProcessP); 
} 

/************************************************************************** 
   The mainline must allocate an AES process resource tag, and set up   
   the AES process structure.  It then schedules the procedure, and     
   continues with normal processing.  When it exits, it must cancel the 
   AES procedure so that it will not continue to reschedule itself even 
   after the mainline has finished executing.                           
*************************************************************************/
void cleanup(void) 
{
   CancelSleepAESProcessEvent(
                             (struct AESProcessStructure *)&mainAESProcess); 
} 

int main(void) 
{

   AtUnload(cleanup);   

   myCount = COUNT_START;  

   /* Allocate an AES process resource tag */
   mainAESResourceTag = AllocateResourceTag(GetNLMHandle(), 
                                            (BYTE *)"My AES Process",  
                                            AESProcessSignature);  

   /* Set up the customized AES process structure */
   mainAESProcess.AWakeUpDelayAmount = DELAY; 
   mainAESProcess.AProcessToCall     = (void *)MyEventProcedure; 
   mainAESProcess.ARTag              = mainAESResourceTag; 
   mainAESProcess.AOldLink           = NULL; 
   mainAESProcess.myValue            = COUNT_START;  

   /* Schedule the first AES procedure */
   ScheduleSleepAESProcessEvent(
                               (struct AESProcessStructure *)&mainAESProcess);  

/************************************************************************** 
  This is the main body of the program.  It executes a thread switch        
  until the values of myCount and GlobalCount are not equal.  The new       
  GlobalCount value is then saved and displayed.  This continues until      
  the count has been incremented to the value of the constant COUNT_END.    
                                                                            
  The result of this loop will be to display the integers 1 through 10,     
  with a one second delay between each display.                             
*************************************************************************/
   while (myCount < COUNT_END)
   {
      while (myCount == GlobalCount)
         ThreadSwitch(); 

      myCount = GlobalCount; 
      printf("%d\n",myCount); 
   } 

   /* Now cancel the rescheduled event before exiting the mainline */ 
   CancelSleepAESProcessEvent(
                             (struct AESProcessStructure *)&mainAESProcess); 

   return(0); 
}  

