/* Producer, 'written' by Joost Boerhout as a help to understand the message
   mechanism of the Amiga. Also see it's counterpart: Consumer.
   Used C compiler: Lattice_C 4.0 */

#include    "exec/types.h"
#include    "exec/nodes.h"
#include    "exec/ports.h"
#include    "exec/memory.h"

struct PCMessage {                  /* Producer-Consumer Message */
   struct Message pc_msg;
   int    item;
} *PCMsg;

APTR             AllocMem();
UBYTE            AllocSignal();
struct Task      *FindTask();
struct MsgPort   *CreatePort();
void             PutMsg(),FreeMem(),DeletePort(),WaitPort(),FreeSignal();
struct PCMessage *GetMsg();
struct MsgPort   *port,*replyport;
UBYTE            signal;

void main()
{
   void  CleanUp();
   int   i;            /* our 'item-holder' */

   if ((port=CreatePort("WareHouse",0))==0) {              /* create a port where items */
      printf("Couldn't create port\n");                    /* will be delivered */
      CleanUp(0);
   }
   if((replyport=CreatePort("WareHouse_reply",0))==0) {    /* create a port where the consumer */
      printf("Couldn't create replyport\n");               /* can dump it's OK-messages */
      CleanUp(1);
   }  
   if ((PCMsg=(struct PCMessage *)AllocMem(sizeof(struct PCMessage ),MEMF_PUBLIC))==0) {
      printf("Not enough memory for message\n");
      CleanUp(2);
   }
   if ((signal=AllocSignal(-1))==-1) {                     /* allocate a signal bit which will */
      printf("Couldn't allocate signal bit\n");            /* be set if someone send a message */
      CleanUp(3);                                          /* to you */
   }

   /*  initialize message and replyport */

   PCMsg->pc_msg.mn_Node.ln_Type=NT_MESSAGE;
   PCMsg->pc_msg.mn_ReplyPort=replyport;
   PCMsg->pc_msg.mn_Length=sizeof(int);
   replyport->mp_Flags|=PA_SIGNAL;
   replyport->mp_SigBit=signal;
   replyport->mp_SigTask=FindTask(0);

   /* Produce 50 messages and wait after each message */

   for (i=1;i<=50;i++) {
      PCMsg->item=i;
      printf("Produced ITEM ...\n");
      PutMsg(port,PCMsg);
      WaitPort(replyport);

      /* Get return message */

      PCMsg=GetMsg(replyport);
      printf("Reply contains ITEM: %d\n",PCMsg->item);
   }

   /* Clean the floor */

   CleanUp(4);
}

void CleanUp(n)
int   n;
{
   switch (n) {
   case 4:
      FreeSignal(signal);
   case 3:
      FreeMem(PCMsg,sizeof(struct PCMessage));
   case 2:
      DeletePort(replyport);
   case 1:
      DeletePort(port);
   case 0:
   }
   exit(0);
}
