home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sys.amiga.programmer
- Path: sparky!uunet!stanford.edu!rock!concert!samba!usenet
- From: Todd_Lewis@unc.edu (Todd M. Lewis)
- Subject: Re: task communication and forbid()
- Message-ID: <1992Dec18.204844.1796@samba.oit.unc.edu>
- Sender: usenet@samba.oit.unc.edu
- Nntp-Posting-Host: guitar.oit.unc.edu
- Organization: UNC Office of Information Technology
- References: <1992Dec18.055155.18152@umr.edu>
- Date: Fri, 18 Dec 1992 20:48:44 GMT
- Lines: 110
-
- In article <1992Dec18.055155.18152@umr.edu> quandt@mcs213b.cs.umr.edu (Brian
- Quandt) writes:
- >I have a question on how to communicate from a subtask to the parent.
- >The main problem is that I need to call forbid so that I can
- >ensure that I get timely response during the while loop. Is it
- >legit to use globals? Is there any special way that these
- >globals need to be declared (memory model) ? I know that task
- >communication via globals and assumed constant memory addresses
- >is ugly but it seems to be the correct way on the amiga. Is it?
- >Is there a better way?
- >
- > {
- > CreateTask( some task that reads keyboard input and sets globalKILL
- > appropriatly )
- >
- > forbid();
- >
- > while(!globalKILL)
- > {
- >
- > }
- >
- > permit();
- > }
-
- Ugh. That's not good. You will waste half of your cycles busy-waiting.
- You want to do a for-real Wait(). Some notes on the code that follows.
- 1) This is off the top of my head--I don't have an Amiga here to
- test it with, so it may not compile, much less work.
- 2) The signal SIGF_SINGLE is pre-allocated for every task so if
- you are just waiting on one thing you can use this "well-known signal".
- Always clear it before waiting on it. That's what simple_wait() is for.
- 3) When you call CreateTask(), you have no way to know if the subtask has
- gotten to run at all by time the call returns, so coordination between
- parent and child tasks is really tricky.
- 4) carefully study the Forbid()/Permit() pairs around the state variable
- examination/change/simple_wait() groups. Follow both threads of
- execution and at every line in the program ask yourself "What happens
- if a task switch occurs here?" I think I've considered all the pitfalls.
-
- ================== coordinate.c =============================
- #include <exec/tasks.h>
-
- #define STARRUNNING 1
- #define RUNNING 2
- #define DROPDEAD 3
- #define DEAD 4
-
- struct Process *mamma_ptr;
- struct Process *child_ptr;
- int state = 0;
- ULONG counter = 0;
-
- void simple_wait( void )
- {
- SetSignal( 0L, SIGF_SINGLE ); /* Clear the signal. */
- Wait( SIGF_SINGLE ); /* Wait for the signal. */
- }
-
- void child( void )
- {
- Forbid();
- while ( state < STARTRUNNING )
- simple_wait();
- Permit();
-
- Forbid();
- state = RUNNING;
- Signal( mamma_ptr, SIGF_SINGLE);
- Permit();
-
- while( state == RUNNING ) /* Do something wonderful. */
- counter++;
-
- Forbid(); /* state should be DROPDEAD. */
- state = DEAD;
- Signal( mamma_ptr, SIGF_SINGLE );
- /* Hanging Forbid() ensures child exits before main() resumes. */
- }
-
- int main( int argc, char *argv[] )
- {
- mamma_ptr = FindTask(0);
- child_ptr = CreatTask("the kid", 0, child, 2048 );
- if ( child_ptr )
- {
- state = STARTRUNNING; /* Tell child to run some more. */
- Signal( child_ptr, SIGF_SINGLE );
-
- Forbid(); /* Wait for child to start running. */
- while ( state < RUNNING )
- simple_wait();
- Permit(); /* Child is running. */
-
- Delay( 250L ); /* Sleep for 5 seconds. */
- /* Do something wonderful. */
- Forbid();
- state = DROPDEAD; /* Tell child to die. */
- simple_wait(); /* Wait for child to die. */
- permit();
- /* child (and state) should be DEAD. */
- }
- return 0;
- }
- =====================================================================
-
- --
- _/_/_/ _/ Todd_Lewis@unc.edu You can lead a horse to
- _/ _/ utoddl@guitar.oit.unc.edu Mohammad, but you can't make
- _/ _/_/_/ a mountain drink a mole hill.
-