home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sys.amiga.programmer
- Path: sparky!uunet!gatech!concert!samba!usenet
- From: Todd_Lewis@unc.edu (Todd M. Lewis)
- Subject: Re: task communication and forbid()
- Message-ID: <1992Dec22.210606.29689@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.204844.1796@samba.oit.unc.edu>
- Date: Tue, 22 Dec 1992 21:06:06 GMT
- Lines: 114
-
- In article <1992Dec18.204844.1796@samba.oit.unc.edu> Todd_Lewis@unc.edu (Todd
- M. Lewis) writes:
- >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.
-
- Well, I took it home and fixed a few things. This example compiles
- and runs under Manx 5.2a. Porting to "other platforms" should
- be simple. If you kept the previous post for reference, replace it
- with this one. Nothing major, but it might save you a few minutes.
-
- ================== coordinate.c =============================
- /********
- Some notes on the code that follows.
- 1) This works under Manx 5.2a. Other C compilers should be easy too.
- 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.
- 5) This is just an example. You should make sure a ^C doesn't kill
- the main() task while child() is running.
- *********************/
-
- #include <exec/tasks.h>
- #ifdef AZTEC_C
- #include <functions.h>
- #endif
-
- #define STARTRUNNING 1
- #define RUNNING 2
- #define DROPDEAD 3
- #define DEAD 4
-
- struct Task *mamma_ptr;
- struct Task *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 )
- {
- #ifdef AZTEC_C
- geta4();
- #endif
- 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 = CreateTask("the kid", 0, child, 2048 );
-
- if ( child_ptr )
- {
- printf("Child task created.\n");
-
- 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. */
-
- printf("Child task is running.\n");
-
- Delay( 250L ); /* Sleep for 5 seconds. */
- /* Do something wonderful. */
- printf("Child has counted to %d.\n", counter );
-
- Forbid();
- state = DROPDEAD; /* Tell child to die. */
- simple_wait(); /* Wait for child to die. */
- Permit();
- /* child (and state) should be DEAD. */
- printf("Child task completed.\n");
- printf("Child has counted to %d.\n", counter );
- }
- 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.
-