home *** CD-ROM | disk | FTP | other *** search
- /*---------------------------------------------
- * TwoTasks.c
- *
- * DUAL TASK Demo in 16-bit Manx C
- *
- * Brian Jackson (B.J. on GEnie)
- *
- * This is just a toy that I wrote to learn how to spawn a child
- * task from a parent. This simply creates a second task that opens
- * a window and draws lines in that window (just like the parent task).
- * In fact, it uses the same NewWindow structure for both tasks. There
- * is some sharing of global variables. You can turn on/off the rendering
- * of the graphics in the child task with Function keys 1 & 2. This is
- * accomplished via message passing (as is the notification that it is
- * time to shut down.) Note that you cannot use any AmigaDOS calls in the
- * child (ie., Delay()) so the timing of things gets a bit tricky.
- *
- * I found that the main hassle is the debugging of the child.
- * Since a spawned task cannot use DOS calls (printf(), puts(), etc.),
- * it's hard to find out why things crashed.
- *
- * Like I said, this was just my own personal toy but, now that it (appears)
- * to work ok, I thought y'all might find it useful as an example.
- *
- * The header files listed in the program may not be complete. I use the
- * Manx pre-compiled headers so the compiler automatically finds ANY thing
- * it might need regardless of what I have listed as header files. You may
- * need to add some.
- *
- * This has been coded to run from the CLI. What with the numerous calls
- * to puts() some minor adjustments would be needed for WB use.
- *
- * compile with: cc TwoTasks.c
- * link with: ln TwoTasks.o -lc
- *
- * Nov 21, 1988
- *--------------------------------------------------
- */
-
- #include <stdio.h>
- #include <intuition/intuition.h>
- #include <functions.h>
- #include <exec/types.h>
- #include <exec/errors.h>
- #include <exec/memory.h>
- #include <devices/timer.h>
- #include <devices/audio.h>
- #include <libraries/dos.h>
- #include <graphics/rastport.h>
-
-
- #define RN 33L /* the current library revision # */
- #define ACTION_START_GRAPHICS 1L
- #define ACTION_STOP_GRAPHICS 2L
- #define ACTION_CLEANUP 3L
- #define FKEY_1 0x50 /* IDCMP Rawkey 'code' values */
- #define FKEY_2 0x51
-
- struct IntuitionBase *IntuitionBase = NULL ;
- struct GfxBase *GfxBase = NULL ;
- struct Window *MW = NULL ;
- struct IntuiMessage *message = NULL ;
- struct Task *secondtask = NULL ;
- struct RastPort *rp = NULL ;
- struct RastPort *rp2 = NULL ;
-
- VOID TaskTwo() ;
- LONG errorval ;
-
- struct MyMessage {
- struct Message msg ;
- LONG Action ;
- } ;
-
- struct MyMessage *T2Msg ;
-
- struct NewWindow newwindow = {
- 0,0,
- 320,199,
- 0,1,
- CLOSEWINDOW| RAWKEY,
- WINDOWDEPTH | WINDOWDRAG
- | SMART_REFRESH | ACTIVATE
- | NOCAREREFRESH | WINDOWCLOSE,
- NULL,
- NULL,
- (UBYTE *)" PARENT ",
- NULL,
- NULL,
- 320,199,
- 320,199,
- WBENCHSCREEN
- };
-
- struct MsgPort *replyport, *task2port ;
-
- VOID _cli_parse() {} /* make stubs of these */
- VOID _wb_parse() {}
-
- main()
- {
-
- ULONG class;
- USHORT code ;
- LONG left = 20L, right = 300L, ypos = 20L, pen = 1L ;
-
- errorval = 0L ;
-
- IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",RN) ;
- if( ! IntuitionBase )
- GetOut ("Error: No Intuition");
-
- GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",RN) ;
- if( ! GfxBase )
- GetOut ("Error: No Graphics.lib");
-
- T2Msg = (struct MyMessage *)AllocMem((LONG)sizeof(*T2Msg), MEMF_PUBLIC) ;
- if( ! T2Msg )
- GetOut("Couldn't alloc memory for T2Msg" ) ;
-
- replyport = (struct MsgPort *)CreatePort( 0L , 0L ) ;
- if( ! replyport )
- GetOut( "Error: no reply port" ) ;
-
- MW = (struct Window *)OpenWindow(&newwindow) ;
- if( ! MW )
- GetOut ("Error: No Window");
-
- rp = MW->RPort ;
-
- secondtask = (struct Task *)CreateTask( "tasktwo", 0L, TaskTwo, 2000L) ;
- if( ! secondtask )
- GetOut( "Can't spawn child" ) ;
-
- Delay( 20L ) ;
-
- task2port = (struct MsgPort *)FindPort( "childport" ) ;
- if( !task2port )
- GetOut( "can't find child port" ) ;
-
- task2port->mp_Node.ln_Type = NT_MSGPORT ;
- task2port->mp_Flags = PA_IGNORE ;
- T2Msg -> msg.mn_Node.ln_Type = NT_MESSAGE ;
- T2Msg -> msg.mn_Length = (LONG)sizeof( struct MyMessage ) ;
- T2Msg -> msg.mn_ReplyPort = replyport ;
-
- SetAPen( rp, 1L ) ;
- Move( rp, 40L, 194L ) ;
- Text( rp, "F1 Stops Child Graphics", 23L ) ;
-
- FOREVER {
-
- if( errorval ) {
- DeleteTask( secondtask ) ;
- Delay( 30L ) ;
- GetOut( "Error: child task didn't start up properly" ) ;
- }
-
- while(message = (struct IntuiMessage *)GetMsg(MW->UserPort)) {
- class = message->Class;
- code = message->Code ;
- ReplyMsg(message);
-
- if (class == CLOSEWINDOW) {
- T2Msg->Action = ACTION_CLEANUP ;
- PutMsg( task2port, T2Msg ) ;
- WaitPort( replyport ) ;
- Delay( 20L ) ; /* wait for exec to kill child */
- GetOut(NULL);
- }
- else if ( class == RAWKEY ) {
- if( code == FKEY_1 )
- T2Msg->Action = ACTION_STOP_GRAPHICS ;
- else if( code == FKEY_2 )
- T2Msg->Action = ACTION_START_GRAPHICS ;
- else
- break ;
- PutMsg( task2port, T2Msg ) ;
- WaitPort( replyport ) ;
- }
- }
-
- if( ++ypos > 180L) {
- ypos = 20L ;
- if( ++pen > 3L )
- pen = 1L ;
- SetAPen( rp, pen ) ;
- }
- Move( rp, left, ypos ) ;
- Draw( rp, right, ypos++ ) ;
- Delay( 1L ) ; /* can't use this in the child! */
-
- } /* end forever */
- } /* end main */
-
-
-
- GetOut( lastword )
- TEXT *lastword ; /* Close things in REVERSE order!! */
- {
- if(MW) CloseWindow(MW);
- if( replyport ) DeletePort( replyport ) ;
- if( T2Msg ) FreeMem( T2Msg, (LONG)sizeof( *T2Msg ) ) ;
- if(GfxBase) CloseLibrary(GfxBase);
- if(IntuitionBase) CloseLibrary(IntuitionBase);
- if( lastword ) puts(lastword) ;
- exit(0) ;
- } /* end function */
-
- UBYTE blockaddress[20] ;
- UBYTE *title ;
-
- /* --------------------------------------------------------
- * This is the child task. It's mostly just like any other
- * stand alone program except that you have to be careful not
- * to use any calls to AmigaDOS functions. (Trust me! :-))
- *
- * The variable 'errorval' is a globals one that both tasks
- * know about. It's the way I let the parent know if problems
- * occurred during the spawning process. If an error occurs,
- * the child sets this variable to non-null and then goes into
- * an infinite Wait(), waiting for the parent to Delete the task.
- *
- * I use the same NewWindow structure except that I kill the
- * CloseWindow and Activate flags as well as adjust the location
- * of it's opening.
- *
- * One other thing to note. Because the child is always busy doing
- * something we just loop and check for messages as we work. If, on
- * the other hand, the child was to be one that was waiting for a
- * message before it did a single act and then waited again, I would
- * replace the FOREVER with a WaitPort() and do "the act" when a
- * message arrived.
- *
- * Also note that before I call DeleteTask() I call Forbid() but never
- * call Permit(). The DeleteTask() function deals with that for you.
- *-----------------------------------------------------------
- */
-
-
- VOID
- TaskTwo()
- {
-
- LONG left = 20L, right = 300L, ypos = 40L, pen = 1L ;
- struct MsgPort *port ;
- struct Window *window ;
- struct IntuiMessage *mess ;
- struct MyMessage *MyMess ;
- LONG what_to_do, x ;
- BOOL do_graphics = TRUE ;
-
- geta4 () ; /* Manx mandatory for use of small code/data ! */
-
- port = (struct MsgPort *)CreatePort( "childport", 0L ) ;
- if( ! port ) {
- errorval == 1L ;
- Wait( 0L ) ;
- }
-
- newwindow.LeftEdge = 315 ; /* fiddle with the window defs */
- newwindow.Title = (UBYTE *)" CHILD " ;
- newwindow.Flags &= ~(WINDOWCLOSE|ACTIVATE) ;
-
- window = (struct Window *)OpenWindow(&newwindow) ;
- if( ! window ) {
- errorval = 2L ;
- DeletePort( port ) ;
- Wait( 0L ) ;
- }
-
- rp2 = window->RPort ;
-
- SetAPen( rp2, 1L ) ;
- Move( rp2, 40L, 194L ) ;
- Text( rp2, "F2 Starts Child Graphics", 24L ) ;
-
-
- FOREVER {
- while( MyMess = (struct MyMessage *)GetMsg( port )) {
- what_to_do = MyMess->Action ;
- ReplyMsg( MyMess ) ;
- if( what_to_do == ACTION_CLEANUP) {
- CloseWindow( window ) ;
- /* Forbid() will prevent any new */
- /* messages from being posted to */
- /* the port until we can close it */
- Forbid() ;
- /* Make sure to empty the port */
- while( MyMess = (struct MyMessage *)GetMsg( port ) ) {
- Remove( MyMess ) ;
- ReplyMsg( MyMess ) ;
- }
- DeletePort( port ) ;
- DeleteTask((struct Task *)FindTask(0L)) ;
- }
- else if( what_to_do == ACTION_START_GRAPHICS )
- do_graphics = TRUE ;
- else if( what_to_do == ACTION_STOP_GRAPHICS )
- do_graphics = FALSE ;
- } /* end while MyMess */
-
- if( do_graphics ) {
- if( ++ypos > 180L) {
- ypos = 20L ;
- if( ++pen > 3L )
- pen = 1L ;
- SetAPen( rp2, pen ) ;
- }
- Move( rp2, left, ypos ) ;
- Draw( rp2, right, ypos++ ) ;
- }
- } /* end forever */
- }
-