home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 362_01 / calldemo.c < prev    next >
C/C++ Source or Header  |  1991-12-10  |  13KB  |  315 lines

  1. /* ////////////////////////////////////////////////////////////////////////////
  2. //                RMAXTask Demonstration                 //
  3. ///////////////////////////////////////////////////////////////////////////////
  4. // DESCRIPTION: A program to demonstrate proper use of RMAXTask calls.         //
  5. //                                         //
  6. // REVISIONS:     9 DEC 91 - RAC - Original code, written for Turbo C.         //
  7. //////////////////////////////////////////////////////////////////////////// */
  8.  
  9. #include    <dos.h>
  10. #include    <conio.h>
  11. #include    <stdio.h>
  12. #include    <stdlib.h>
  13. #include    <alloc.h>
  14. #include    "\rmaxtask\source\rmaxtask.h"
  15.  
  16. /* ////////////////////////////////////////////////////////////////////////////
  17. //    Some global data                                 //
  18. //////////////////////////////////////////////////////////////////////////// */
  19.  
  20. TDESC    *mailbox_ptr;                /* Pointers to mailboxes and */
  21. TDESC    *semaphore_1_ptr;            /*  semaphores */
  22. TDESC    *semaphore_2_ptr;
  23. TDESC    *keystroke_mailbox_ptr;
  24.  
  25. /* ////////////////////////////////////////////////////////////////////////////
  26. //                break_handler()                     //
  27. //                atexit_handler()                 //
  28. ///////////////////////////////////////////////////////////////////////////////
  29. // DESCRIPTION:    Since it is necessary to call stop_RMAXTask() when the         //
  30. //        program terminates, we install a Ctrl-Break handler that     //
  31. //        makes the call in case the user presses Ctrl-Break while     //
  32. //        the program is running.  We also register a handler using    //
  33. //        the atexit() function so it takes care of all other exits    //
  34. //        from the program.                         //
  35. //                                         //
  36. // REVISIONS:     9 DEC 91 - RAC - Adapted from previous work.             //
  37. //////////////////////////////////////////////////////////////////////////// */
  38.  
  39. void atexit_handler() {
  40.     printf("atexit_handler():  RMAX_time() at end = %ld\n", RMAX_time());
  41.     stop_RMAXTask();                /* Do 'about to die' cleanup */
  42.     printf("atexit_handler():  RMAXTask() shut down properly.\n");
  43.     }                        /* End break_handler() */
  44.  
  45. int break_handler() {
  46.     atexit_handler();
  47.     return 0;                    /* This will abort program */
  48.     }                        /* End break_handler() */
  49.  
  50. /* ////////////////////////////////////////////////////////////////////////////
  51. //                keyboard_task()                     //
  52. ///////////////////////////////////////////////////////////////////////////////
  53. // DESCRIPTION:    This task continuously waits for some other task to send it  //
  54. //        mail in the keystroke mailbox.  If it does not get mail at   //
  55. //        least once every two seconds, it complains.  When it does    //
  56. //        get mail, it is appropriately grateful.                 //
  57. //                                         //
  58. // REVISIONS:    10 DEC 91 - RAC - Original code.                 //
  59. //////////////////////////////////////////////////////////////////////////// */
  60.  
  61. void keyboard_task() {
  62.  
  63.     char    msg[40];
  64.     unsigned    msg_size;
  65.  
  66.     for (;;) {                    /* Repeat forever */
  67.     get_mail(msg, &msg_size,        /* Wait 2 seconds for a */
  68.          keystroke_mailbox_ptr, 2 * 18,    /*  keystroke */
  69.          0);
  70.     if (get_status() == TIMEOUT)        /* Nag for keyboard activity */
  71.         printf("keyboard_task():  I want a keystroke\n");
  72.     else
  73.         printf("keyboard_task():  Thanks for the '%c'  Press <Esc> to quit\n", msg[0]);
  74.     }                    /* End 'repeat forever' */    
  75.     }                        /* End keyboard_task() */
  76.  
  77. /* ////////////////////////////////////////////////////////////////////////////
  78. //                 clock_task()                     //
  79. ///////////////////////////////////////////////////////////////////////////////
  80. // DESCRIPTION: This task just displays the DOS time on the screen's first   //
  81. //        line.                                 //
  82. //                                         //
  83. // REVISIONS:    10 DEC 91 - RAC - Original code                     //
  84. //////////////////////////////////////////////////////////////////////////// */
  85.  
  86. void clock_task() {
  87.  
  88.     int    wrow, wcol;                /* Save cursor position here */
  89.     struct time now;                /* Read time into here */
  90.     static int last_sec = 99;
  91.  
  92.     for (;;) {                    /* Repeat forever */
  93.     gettime(&now);                /* Get DOS time */
  94.     if (now.ti_sec != last_sec) {        /* Do only if new second */
  95.         last_sec = now.ti_sec;        /* Note current second */
  96.         wrow = wherey();            /* Save cursor position */
  97.         wcol = wherex();            /* Save cursor position */
  98.         gotoxy(47, 1);            /* Update time display */
  99.         printf("   clock_task():  %02d:%02d:%02d",
  100.            now.ti_hour,
  101.            now.ti_min,
  102.            now.ti_sec);
  103.         gotoxy(47, 2);
  104.         printf("                       ");
  105.         gotoxy(wcol, wrow);            /* Restore cursor position */
  106.         }                    /* End 'new second' */
  107.     suspend(3);                /* Sleep for 2-3 ticks */
  108.     }                    /* End 'repeat forever' */
  109.     }                        /* End clock_task() */
  110.     
  111. /* ////////////////////////////////////////////////////////////////////////////
  112. //                   brigade_1_task()                     //
  113. //                   brigade_2_task()                     //
  114. ///////////////////////////////////////////////////////////////////////////////
  115. // DESCRIPTION:    These two tasks together with main() form a "message         //
  116. //        brigade" where main() periodically kicks brigade_1_task()    //
  117. //        into action via a semmaphore.  brigade_1_task() then sends   //
  118. //        mail to brigade_2_task(), which in turn signals main() that  //
  119. //        the brigade is complete.                     //
  120. //                                         //
  121. // REVISIONS:    10 DEC 91 - RAC - Original code.                 //
  122. //////////////////////////////////////////////////////////////////////////// */
  123.  
  124. void brigade_1_task() {
  125.  
  126.     int        i;                /* Generic integer */
  127.  
  128.     for (;;) {
  129.     wait_sem(semaphore_2_ptr, 0);
  130.     printf("brigade_1_task():  Got signal from main()\n");
  131.     i = send_mail("Hello, Brigade #2",  20, mailbox_ptr);
  132.     if (!i) {
  133.         printf("brigade_1_task():  send_mail() failed\n");
  134.         exit(1);
  135.         }
  136.     }
  137.     }
  138.  
  139. void brigade_2_task() {
  140.  
  141.     char    msg[40];
  142.     unsigned    msg_size;
  143.  
  144.     for (;;) {
  145.     get_mail(msg, &msg_size, mailbox_ptr, 0, 0);
  146.     printf("brigade_2_task():  Received '%s' from brigade_1_task()\n", msg);
  147.     signal_sem(semaphore_1_ptr);
  148.     }
  149.     }
  150.  
  151. /* ////////////////////////////////////////////////////////////////////////////
  152. //                    main()                     //
  153. ///////////////////////////////////////////////////////////////////////////////
  154. // DESCRIPTION: The mother of all tasks.  It runs a demo that shows how         //
  155. //        RMAXTask functions should be called and used.  There are     //
  156. //        two parts to the demo.  The first demonstrates inter-task    //
  157. //        communication via semaphores and mailboxes with the message  //
  158. //        brigade outlined in the description of brigade_1_task() and  //
  159. //        brigade_2_task().  The second part of the demo shows more    //
  160. //        of the same sort of stuff, with emphasis on the keyboard     //
  161. //        functions and on timing events within a program.         //
  162. //                                         //
  163. // REVISIONS:     9 DEC 91 - RAC - Original code                     //
  164. //////////////////////////////////////////////////////////////////////////// */
  165.  
  166. void main() {
  167.  
  168.     int        i;                /* Generic integer */
  169.     struct time now;                /* Read time into here */
  170.     TDESC    *tp;                /* Generic task pointer */
  171.  
  172. /* ////////////////////////////////////////////////////////////////////////////
  173.      Start by setting up a Ctrl-Break handler and an "atexit" handler to
  174.      make sure that stop_RMAXTask() is called when the program terminates.
  175.      If stop_RMAXTask() is NOT called before returning to DOS, the PC's
  176.      interrupt vector table will be left in an unfortunate state and the
  177.      computer will almost certainly crash when you try to run another
  178.      transient application.
  179. //////////////////////////////////////////////////////////////////////////// */
  180.  
  181.     clrscr();                    /* Clear the screen */
  182.     ctrlbrk(break_handler);            /* Establish break handler */
  183.     atexit(atexit_handler);            /* Register exit function */
  184.  
  185. /* ////////////////////////////////////////////////////////////////////////////
  186.      Start up the RMAXTask software and create all the tasks used by this
  187.      program.  Note that the RMAXTask functions almost all return error
  188.      codes which should be checked to make sure things are working properly.
  189. //////////////////////////////////////////////////////////////////////////// */
  190.  
  191.     printf("main():  %ld bytes free initially\n", /* Report available memory */
  192.        coreleft());                /*  size */
  193.     if (!start_RMAXTask()) {            /* Initialize RMAXTask, or */
  194.     printf("main():  start_RMAXTask() failed\n"); /*  die trying */
  195.     exit(1);
  196.     }
  197.     printf("main():  RMAX_time() to start = %ld\n", RMAX_time());
  198.  
  199. /*  Create all the tasks, or die trying  */
  200.  
  201.     i = 0;                    /* Assume no task failure */
  202.     tp = create_task("clock_task",        /* Create a task to display */
  203.              clock_task,        /*  the time every once in a */
  204.              STANDARD_PRIORITY + 1,    /*  while. */
  205.              STANDARD_STACK);
  206.     i |= (tp == NULL);
  207.     tp = create_task("brigade_1_task",        /* Create the 1st task in */
  208.              brigade_1_task,        /*  message brigade */
  209.              STANDARD_PRIORITY,
  210.              STANDARD_STACK);
  211.     i |= (tp == NULL);
  212.     tp = create_task("brigade_2_task",        /* Create the 2nd task in */
  213.              brigade_2_task,        /*  message brigade */
  214.              STANDARD_PRIORITY,
  215.              STANDARD_STACK);
  216.     i |= (tp == NULL);
  217.     if (i) {                    /* Die if the tasks weren't */
  218.     printf("main():  create_task() failed\n"); /*  all created properly */
  219.     exit(1);
  220.     }
  221.  
  222. /*  Note memory left so we can tell how much the tasks take up  */
  223.  
  224.     printf("main():  %ld bytes free after tasks" /* Report available memory */
  225.        " created\n", coreleft());         /*  size */
  226.  
  227. /* ////////////////////////////////////////////////////////////////////////////
  228.      Now create the needed semaphores and mailboxes.  Pointers to the
  229.      objects created are kept globally so that they can be accessed by all
  230.      the tasks.
  231. //////////////////////////////////////////////////////////////////////////// */
  232.  
  233.     mailbox_ptr = create_mailbox();
  234.     if (mailbox_ptr == NULL) {
  235.     printf("main():  create_mailbox() failed\n");
  236.     exit(1);
  237.     }
  238.     keystroke_mailbox_ptr = create_mailbox();
  239.     if (keystroke_mailbox_ptr == NULL) {
  240.     printf("main():  create_mailbox() failed\n");
  241.     exit(1);
  242.     }
  243.     semaphore_1_ptr = create_sem(0);
  244.     if (semaphore_1_ptr == NULL) {
  245.     printf("main():  create_sem() failed\n");
  246.     exit(1);
  247.     }
  248.     semaphore_2_ptr = create_sem(0);
  249.     if (semaphore_2_ptr == NULL) {
  250.     printf("main():  create_sem() failed\n");
  251.     exit(1);
  252.     }
  253.  
  254. /*  Again, note memory left so we can see what's going on  */
  255.  
  256.     printf("main():  %ld bytes free after mailbox and"     /* Report available memory */
  257.        " semaphores created\n", coreleft()); /*  size */
  258.  
  259. /* ////////////////////////////////////////////////////////////////////////////
  260.      Here begins the "message brigade".  See the descriptions for
  261.      brigade_1_task() and brigade_2_task() for details on what's happening
  262.      here.
  263. //////////////////////////////////////////////////////////////////////////// */
  264.  
  265.     for (i=0; i<3; i++) {            /* Do this gig three times */
  266.     suspend(2 * 18.2);            /* Wait 2 seconds */
  267.     signal_sem(semaphore_2_ptr);        /* Start the task brigade */
  268.     wait_sem(semaphore_1_ptr, 18);        /* Wait for it to finish */
  269.     if (get_status() == TIMEOUT)        /* Make sure all is well */
  270.         printf("main():  Task brigade failure\n");
  271.     else        
  272.         printf("main():  Successful task brigade action\n");
  273.     }
  274.  
  275.     printf("main():  Done with task brigade demonstration\n\n");
  276.  
  277. #define ESC_KEY 0x011b                          /* Keycode for <Esc> */
  278.  
  279.     printf("main():  Begin keyboard demonstration.\n");
  280.     tp = create_task("keyboard_task",        /* Create the keyboard task */
  281.              keyboard_task,
  282.              STANDARD_PRIORITY,
  283.              STANDARD_STACK);
  284.     if (tp == NULL) {
  285.     printf("main():  create_task() failed\n");
  286.     exit(1);
  287.     }
  288.     do {
  289.     i = wait_key(18.2 * 5);
  290.     if (get_status() == TIMEOUT) {
  291.         printf("main():  Faking a keypress\n");
  292.         fake_key('A');
  293.         }
  294.     else
  295.         send_mail(&i, sizeof(i), keystroke_mailbox_ptr);
  296.     } while (i != ESC_KEY);
  297.     kill_task(tp);                /* Kill the keyboard task */
  298.  
  299. /* ////////////////////////////////////////////////////////////////////////////
  300.      Pay special attention to this next 'do' loop.  It shows shows a
  301.      technique for waiting on events that are not integrated into the
  302.      RMAXTask software, while still allowing other tasks to run.  Here we
  303.      wait on a particular condition of the DOS clock.  You might need to
  304.      wait for an interrupt or a mouse event in a similar way.
  305. //////////////////////////////////////////////////////////////////////////// */
  306.  
  307.     printf("main():  Program will terminate when the DOS clock reaches the next\n"
  308.        "even multiple of 10 seconds\n");
  309.     do {
  310.     yield();
  311.     gettime(&now);
  312.     } while (now.ti_sec % 10);
  313.     stop_RMAXTask();                /* Shut down RMAXTask */
  314.     }
  315.