
#include <exec/exec.h>
#include <proto/exec.h>
#include <proto/dos.h>

#include "queue.h"
#include "queue_inline.h"

struct ExecBase *SysBase = NULL;
struct DosLibrary *DOSBase = NULL;
struct Library *QueueBase = NULL;

typedef struct {
  QMessage qmsg;
  char     contents;
} MyQMessage;

Block (int *abort)
{
  int r;

  if (r = rand () % 3)
    Delay (r * 5);
  if (SetSignal (0, SIGBREAKF_CTRL_F) & SIGBREAKF_CTRL_F)
    *abort = 1;
}

int
main (int argc, char *argv[])
{
  ULONG sigbit, sigmask;
  MyQMessage qmsg, *msg;
  QHandle qh;
  char *queuename = "testqueue";
  char contents = 0;
  int r, abort = 0;

  if (argc == 2)
  {
    contents = argv[1][0];
  }
  SysBase = *(struct ExecBase **)4;
  if (!(DOSBase = (struct DosLibrary *) OpenLibrary ("dos.library", 37)))
    return 1;

  if ((sigbit = AllocSignal (-1)) == -1)
  {
    printf ("Failed to allocate signal.\n");
    return 1;
  }
  sigmask = 1 << sigbit;
  msg = &qmsg;

  if (!(QueueBase = OpenLibrary ("queue.library", 0)))
  {
    printf ("Failed to open queue.library.\n");
    return 1;
  }
  if (!(qh = QOpen (queuename, contents ? QMODE_SEND : QMODE_LISTEN, sigbit)))
  {
    printf ("Failed to open \"%s\" queue.\n", queuename);
    return 1;
  }
  if (!contents) /* Client */
  {
    while (1)
    {
      if (abort || Wait (sigmask | SIGBREAKF_CTRL_F) & SIGBREAKF_CTRL_F)
      {
	Forbid ();
        while (msg = (MyQMessage *) QGetMsg (qh));
	QClose (qh);
	Permit ();
        printf ("Exiting.\n");
	return 0;
      }
      printf ("Signal.\n");

      if (rand () % 2) /*** Process all messages ***/
      {
        while (msg = (MyQMessage *) QGetMsg (qh))
	  printf ("Got message %c.\n", msg -> contents);
      }
      else /*** Reply message & block ***/
      {
        if (msg = (MyQMessage *) QGetMsg (qh))
	  printf ("Got message %c (replying,blocking).\n", msg -> contents);

        if (r = rand () % 2)
        {
	  QReplyMsg (qh);
          Block (&abort);
        }
        else
        {
          Block (&abort);
	  QReplyMsg (qh);
        }
      }
    }
  }
  else
  {
    msg -> contents = contents;

    while (1)
    {
      if (!abort)
      {
        if (msg -> contents < '9')
        {
	  msg -> contents ++;
	  printf ("Next message: %c.\n", msg -> contents);
        }
        QAddMsg (qh, (QMessage *) msg);
      }
      if (abort || Wait (sigmask | SIGBREAKF_CTRL_F) & SIGBREAKF_CTRL_F)
      {
        while ((r = QClose (qh)) > 0)
        {
          printf ("Cannot exit: %d messages left in queue.\n", r);
	  Delay (10);
          QGetMsg (qh);
        }
        printf ("All done.\n");
        return 0;
      }
      printf ("Signal.\n");
      if (QGetMsg (qh) == (QMessage *) msg)
        printf ("Got my message (%c).\n", msg -> contents);
      else
        printf ("Got wrong message (%c).\n", msg -> contents);

      Block (&abort);
    }
  }
}
