home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / programming / source / twotasks.lha / TwoTasks.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-22  |  9.9 KB  |  315 lines

  1. /*---------------------------------------------
  2.  * TwoTasks.c
  3.  *
  4.  * DUAL TASK Demo in 16-bit Manx C   
  5.  *
  6.  * Brian Jackson (B.J. on GEnie)
  7.  *
  8.  * This is just a toy that I wrote to learn how to spawn a child
  9.  * task from a parent.  This simply creates a second task that opens
  10.  * a window and draws lines in that window (just like the parent task).
  11.  * In fact, it uses the same NewWindow structure for both tasks.  There
  12.  * is some sharing of global variables.  You can turn on/off the rendering
  13.  * of the graphics in the child task with Function keys 1 & 2.  This is
  14.  * accomplished via message passing (as is the notification that it is
  15.  * time to shut down.)  Note that you cannot use any AmigaDOS calls in the
  16.  * child (ie., Delay()) so the timing of things gets a bit tricky.
  17.  *
  18.  * I found that the main hassle is the debugging of the child.
  19.  * Since a spawned task cannot use DOS calls (printf(), puts(), etc.), 
  20.  * it's hard to find out why things crashed.  
  21.  *
  22.  * Like I said, this was just my own personal toy but, now that it (appears)
  23.  * to work ok, I thought y'all might find it useful as an example.
  24.  *
  25.  * The header files listed in the program may not be complete.  I use the
  26.  * Manx pre-compiled headers so the compiler automatically finds ANY thing
  27.  * it might need regardless of what I have listed as header files. You may 
  28.  * need to add some.
  29.  *
  30.  * This has been coded to run from the CLI. What with the numerous calls
  31.  * to puts() some minor adjustments would be needed for WB use.
  32.  * 
  33.  *  compile with:    cc TwoTasks.c
  34.  *  link with:       ln TwoTasks.o -lc
  35.  *
  36.  *   Nov 21, 1988
  37.  *--------------------------------------------------
  38.  */
  39.  
  40.  #include <stdio.h>
  41.  #include <intuition/intuition.h>
  42.  #include <functions.h>
  43.  #include <exec/types.h>
  44.  #include <exec/errors.h>
  45.  #include <exec/memory.h>
  46.  #include <devices/timer.h>
  47.  #include <devices/audio.h>
  48.  #include <libraries/dos.h>
  49.  #include <graphics/rastport.h>
  50.  
  51.  
  52.  #define  RN          33L              /* the current library revision # */
  53.  #define  ACTION_START_GRAPHICS  1L
  54.  #define  ACTION_STOP_GRAPHICS   2L
  55.  #define  ACTION_CLEANUP         3L
  56.  #define  FKEY_1                 0x50  /* IDCMP Rawkey 'code' values */
  57.  #define  FKEY_2                 0x51
  58.  
  59.  struct IntuitionBase *IntuitionBase = NULL ;
  60.  struct GfxBase       *GfxBase       = NULL ;
  61.  struct Window        *MW            = NULL ;
  62.  struct IntuiMessage  *message       = NULL ;
  63.  struct Task          *secondtask    = NULL ;
  64.  struct RastPort      *rp            = NULL ; 
  65.  struct RastPort      *rp2           = NULL ;
  66.  
  67.  VOID   TaskTwo() ;
  68.  LONG   errorval ;
  69.  
  70.  struct MyMessage {
  71.      struct Message msg ;
  72.      LONG Action ;
  73.      } ; 
  74.  
  75.  struct MyMessage *T2Msg ;
  76.  
  77.  struct NewWindow newwindow = {
  78.      0,0,
  79.      320,199,
  80.      0,1,
  81.      CLOSEWINDOW| RAWKEY,
  82.      WINDOWDEPTH | WINDOWDRAG
  83.       | SMART_REFRESH | ACTIVATE 
  84.       | NOCAREREFRESH | WINDOWCLOSE,
  85.      NULL,
  86.      NULL,
  87.      (UBYTE *)" PARENT ",
  88.      NULL,
  89.      NULL,
  90.      320,199,
  91.      320,199,
  92.      WBENCHSCREEN
  93.      };
  94.  
  95.  struct MsgPort *replyport, *task2port ;
  96.  
  97.  VOID _cli_parse() {}               /* make stubs of these */
  98.  VOID _wb_parse() {}
  99.  
  100.  main()
  101.  {
  102.  
  103.  ULONG class;
  104.  USHORT code ;
  105.  LONG left = 20L, right = 300L, ypos = 20L, pen = 1L ;
  106.  
  107.    errorval = 0L ;
  108.  
  109.    IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",RN) ;
  110.    if( ! IntuitionBase )
  111.        GetOut ("Error:  No Intuition");
  112.  
  113.    GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",RN) ;
  114.    if( ! GfxBase )
  115.        GetOut ("Error:  No Graphics.lib");
  116.  
  117.    T2Msg = (struct MyMessage *)AllocMem((LONG)sizeof(*T2Msg), MEMF_PUBLIC) ;
  118.    if( ! T2Msg )  
  119.        GetOut("Couldn't alloc memory for T2Msg" ) ;
  120.  
  121.    replyport = (struct MsgPort *)CreatePort( 0L , 0L ) ;
  122.    if( ! replyport ) 
  123.        GetOut( "Error: no reply port" ) ;
  124.  
  125.    MW = (struct Window *)OpenWindow(&newwindow) ;
  126.    if( ! MW )
  127.        GetOut ("Error:  No Window");
  128.  
  129.    rp = MW->RPort ;
  130.  
  131.    secondtask = (struct Task *)CreateTask( "tasktwo", 0L, TaskTwo, 2000L) ;
  132.    if( ! secondtask ) 
  133.        GetOut( "Can't spawn child" ) ;
  134.  
  135.    Delay( 20L ) ;
  136.  
  137.    task2port = (struct MsgPort *)FindPort( "childport" ) ;
  138.    if( !task2port )  
  139.        GetOut( "can't find child port" ) ;
  140.        
  141.    task2port->mp_Node.ln_Type   = NT_MSGPORT ;
  142.    task2port->mp_Flags          = PA_IGNORE ;
  143.    T2Msg -> msg.mn_Node.ln_Type = NT_MESSAGE ;
  144.    T2Msg -> msg.mn_Length       = (LONG)sizeof( struct MyMessage ) ;
  145.    T2Msg -> msg.mn_ReplyPort    = replyport ;
  146.  
  147.    SetAPen( rp, 1L ) ;
  148.    Move( rp, 40L, 194L ) ;
  149.    Text( rp, "F1 Stops Child Graphics", 23L ) ;
  150.  
  151.    FOREVER  {
  152.  
  153.        if( errorval ) {
  154.            DeleteTask( secondtask ) ;
  155.            Delay( 30L ) ;
  156.            GetOut( "Error: child task didn't start up properly" ) ;
  157.            }
  158.  
  159.        while(message = (struct IntuiMessage *)GetMsg(MW->UserPort)) {
  160.            class = message->Class;
  161.            code  = message->Code ;
  162.            ReplyMsg(message);
  163.  
  164.            if (class == CLOSEWINDOW)  {
  165.                T2Msg->Action = ACTION_CLEANUP ;
  166.                PutMsg( task2port, T2Msg ) ;
  167.                WaitPort( replyport ) ;
  168.                Delay( 20L ) ;         /* wait for exec to kill child */
  169.                GetOut(NULL);
  170.                }
  171.            else if ( class == RAWKEY ) {
  172.                if( code == FKEY_1 )
  173.                    T2Msg->Action = ACTION_STOP_GRAPHICS ;
  174.                else if( code == FKEY_2 )
  175.                    T2Msg->Action = ACTION_START_GRAPHICS ;
  176.                else 
  177.                    break ;
  178.                PutMsg( task2port, T2Msg ) ;
  179.                WaitPort( replyport ) ;
  180.                }
  181.            }
  182.  
  183.        if( ++ypos > 180L)  {
  184.            ypos = 20L ;
  185.            if( ++pen > 3L ) 
  186.                pen = 1L ;
  187.            SetAPen( rp, pen ) ;
  188.            }
  189.        Move( rp, left, ypos ) ;
  190.        Draw( rp, right, ypos++ ) ;
  191.        Delay( 1L ) ;                 /* can't use this in the child! */
  192.  
  193.        }                                /* end forever           */
  194.   }                                     /* end main              */
  195.  
  196.  
  197.  
  198.  GetOut( lastword )
  199.  TEXT *lastword ;             /* Close things in REVERSE order!! */
  200.  {
  201.      if(MW)               CloseWindow(MW);
  202.      if( replyport )      DeletePort( replyport ) ;
  203.      if( T2Msg )          FreeMem( T2Msg, (LONG)sizeof( *T2Msg ) ) ;
  204.      if(GfxBase)          CloseLibrary(GfxBase);
  205.      if(IntuitionBase)    CloseLibrary(IntuitionBase);
  206.      if( lastword )       puts(lastword) ;
  207.      exit(0) ;
  208.  }      /* end function */
  209.  
  210.  UBYTE blockaddress[20] ;
  211.  UBYTE *title ;
  212.  
  213.  /* --------------------------------------------------------
  214.   * This is the child task.  It's mostly just like any other
  215.   * stand alone program except that you have to be careful not
  216.   * to use any calls to AmigaDOS functions.  (Trust me! :-))
  217.   *
  218.   * The variable 'errorval' is a globals one that both tasks
  219.   * know about.  It's the way I let the parent know if problems
  220.   * occurred during the spawning process.  If an error occurs,
  221.   * the child sets this variable to non-null and then goes into
  222.   * an infinite Wait(), waiting for the parent to Delete the task.
  223.   *
  224.   * I use the same NewWindow structure except that I kill the
  225.   * CloseWindow and Activate flags as well as adjust the location
  226.   * of it's opening.
  227.   *
  228.   * One other thing to note.  Because the child is always busy doing
  229.   * something we just loop and check for messages as we work. If, on
  230.   * the other hand, the child was to be one that was waiting for a
  231.   * message before it did a single act and then waited again, I would
  232.   * replace the FOREVER with a WaitPort() and do "the act" when a 
  233.   * message arrived.
  234.   *
  235.   * Also note that before I call DeleteTask() I call Forbid() but never
  236.   * call Permit().  The DeleteTask() function deals with that for you.
  237.   *-----------------------------------------------------------
  238.   */
  239.  
  240.  
  241.  VOID
  242.  TaskTwo()
  243.  {
  244.  
  245.  LONG left = 20L, right = 300L, ypos = 40L, pen = 1L ;
  246.  struct MsgPort *port ;
  247.  struct Window *window ;
  248.  struct IntuiMessage *mess ;
  249.  struct MyMessage *MyMess ;
  250.  LONG   what_to_do, x ;
  251.  BOOL   do_graphics = TRUE ;
  252.  
  253.   geta4 () ;   /* Manx mandatory for use of small code/data ! */
  254.  
  255.   port = (struct MsgPort *)CreatePort( "childport", 0L ) ;
  256.   if( ! port ) {
  257.       errorval == 1L ;
  258.       Wait( 0L ) ;
  259.       }
  260.  
  261.   newwindow.LeftEdge = 315 ;   /* fiddle with the window defs */
  262.   newwindow.Title = (UBYTE *)" CHILD " ;
  263.   newwindow.Flags &= ~(WINDOWCLOSE|ACTIVATE) ;
  264.  
  265.   window = (struct Window *)OpenWindow(&newwindow) ;
  266.   if( ! window ) {
  267.       errorval = 2L  ;
  268.       DeletePort( port ) ;
  269.       Wait( 0L ) ;
  270.       }
  271.  
  272.   rp2 = window->RPort ;
  273.  
  274.   SetAPen( rp2, 1L ) ;
  275.   Move( rp2, 40L, 194L ) ;
  276.   Text( rp2, "F2 Starts Child Graphics", 24L ) ;
  277.  
  278.  
  279.   FOREVER  {
  280.       while( MyMess = (struct MyMessage *)GetMsg( port )) {
  281.           what_to_do = MyMess->Action ;
  282.           ReplyMsg( MyMess ) ;
  283.           if( what_to_do == ACTION_CLEANUP) {
  284.               CloseWindow( window ) ;
  285.                                       /* Forbid() will prevent any new  */
  286.                                       /* messages from being posted to  */
  287.                                       /* the port until we can close it */
  288.               Forbid() ;           
  289.                                       /* Make sure to empty the port    */
  290.               while( MyMess = (struct MyMessage *)GetMsg( port ) ) {
  291.                   Remove( MyMess ) ;
  292.                   ReplyMsg( MyMess ) ;
  293.                   }
  294.               DeletePort( port ) ;
  295.               DeleteTask((struct Task *)FindTask(0L)) ;
  296.               }
  297.           else if( what_to_do == ACTION_START_GRAPHICS )
  298.               do_graphics = TRUE ;
  299.           else if( what_to_do == ACTION_STOP_GRAPHICS )
  300.               do_graphics = FALSE ;
  301.           }                           /* end while MyMess     */
  302.           
  303.       if( do_graphics ) {
  304.           if( ++ypos > 180L)  {
  305.               ypos = 20L ;
  306.               if( ++pen > 3L ) 
  307.                   pen = 1L ;
  308.               SetAPen( rp2, pen ) ;
  309.               }
  310.           Move( rp2, left, ypos ) ;
  311.           Draw( rp2, right, ypos++ ) ;
  312.           }
  313.       }                                /* end forever           */
  314.  }
  315.