[alt.sources.amiga] Signal Semaphores/multiple Tasks example

dylan@june.cs.washington.edu (Dylan McNamee) (04/30/91)

If anyone else has examples like this one floating around their personal
source collections, I for one would love to see them!
---begin included C source file----
/* 
   SemaphoreTasks.c
   by dylan mcnamee
      dylan@cs.washington.edu

   This is a short example of multiple tasks communicating
   through shared variables, with synchronization accomplished
   with Signal Semaphores.  This kind of communication is much
   more efficient than messages, in applicable cases.  

   I couldn't find any examples of Signal Semaphores in use,
   hence this creation & posting.

   In this program, there are two semaphores, one protecting the
   ReqTaskDie variable, and the other protecting the canonical
   shared integer, which a few tasks take turns incrementing.

   Note that it is the responsibility of the programmer to make
   sure that all uses of "protected" variables are surrounded by
   the appropriate Obtain/ReleaseSemaphore calls, and that 
   the Obtains are matched exactly by Releases.

   This example is in the public domain.  (Yea, like there's 
   anything original in it!)

   This is compilable under SAS, with the -v -y flags, to suppress
   stack checking, and "do the right thing" on task entry.  If there's
   enough demand, I'll Manx-ify things.
 */
#include <stdio.h>
#define GRAPHICS_REV 29
#define new(x) (x *)(AllocMem(sizeof(x),MEMF_CLEAR | MEMF_PUBLIC))           
#define free(x) FreeMem(x, sizeof(x))

#define NUM_TASKS 3
struct Task *count_task_tcb = 0L;
struct Task *count_task2_tcb = 0L;
struct Task *count_task3_tcb = 0L;

int ReqTaskDie;
struct SignalSemaphore *ReqTaskDieSem = 0L;

int shared;
struct SignalSemaphore *SharedSem = 0L;

struct GfxBase *GfxBase = 0L; /* WaitTOF() lives here */


extern void count_task();
extern void exit_clean();

/* =========================================================*/
/* create some synchronizing tasks, then shut them down with a
   shared, semaphore protected, variable
 */
main()
{
char wait_char;
shared = 0;
ReqTaskDie = 0;

GfxBase = (struct GfxBase*)OpenLibrary("graphics.library",GRAPHICS_REV);           
if(!GfxBase) exit_clean();

/* Two signal semaphores initialized */
ReqTaskDieSem = new(struct SignalSemaphore);
SharedSem = new(struct SignalSemaphore);
if((!SharedSem) || (!ReqTaskDieSem))exit_clean();

InitSemaphore(ReqTaskDieSem);
InitSemaphore(SharedSem);

/* create some tasks */
count_task_tcb = CreateTask("counting task", 0, (APTR)count_task, 1000L);
count_task2_tcb = CreateTask("counting task2", 0, (APTR)count_task, 1000L);
count_task3_tcb = CreateTask("counting task3", 0, (APTR)count_task, 1000L);

if((!count_task_tcb) || (!count_task2_tcb) || (!count_task3_tcb)){
  fprintf(stderr,"Couldn't create task...\n");
  exit_clean();
  }

ObtainSemaphore(SharedSem);
printf("shared var %d\n",shared);                                    
ReleaseSemaphore(SharedSem);

printf("press return");
scanf("%c\n",&wait_char);


ObtainSemaphore(ReqTaskDieSem);
ReqTaskDie = NUM_TASKS;
ReleaseSemaphore(ReqTaskDieSem);

/* wait for all tasks to acknowledge Die signal */
while(ReqTaskDie){                                                       
  WaitTOF();
  }                                                                    

printf("shared var %d\n",shared);

exit_clean();
}

/* =========================================================*/
/* a simple subtask, with death accomplished by a handshake */
void count_task()
{

/* do something for awhile */
while(!ReqTaskDie){
  WaitTOF();
  ObtainSemaphore(SharedSem);
  shared++;
  ReleaseSemaphore(SharedSem);
  }

/* now ack die */

ObtainSemaphore(ReqTaskDieSem);
ReqTaskDie--;
ReleaseSemaphore(ReqTaskDieSem);

Wait(0L);
}


/* =========================================================*/
/* free all resources successfully gained */
void
exit_clean()
{
if(count_task_tcb)
  RemTask(count_task_tcb);
if(count_task2_tcb)
  RemTask(count_task2_tcb);
if(count_task3_tcb)
  RemTask(count_task3_tcb);

if(GfxBase!=NULL)
  CloseLibrary((struct Library *)GfxBase);

if(ReqTaskDieSem)
  free(ReqTaskDieSem);
if(SharedSem)
  free(SharedSem);
}
-- 
dylan mcnamee             / "I stood there on the sidewalk, Roy Rogers       
dylan@cs.washington.edu \/lunchpail in my hand.  Then I heard sweet children's 
     Qua!                voices...and I began to understand." Randy Newman