/***********************************************/
/* odindemo1.c                                 */
/* demo of odin.library                        */
/* starts 2 new processes and sends envelopes  */
/* back and forth.                             */
/* Created 7-Jul-90 by Peter Oerbaek           */
/* This code is in the public domain.          */
/* Link with odinglue.o                        */
/***********************************************/

/**********************************************************************
  A lot of checking is ommited in the code to make it smaller and
  easier to read.
**********************************************************************/

#include	"exec/types.h"
#include	"exec/semaphores.h"
#include	"stdio.h"
#include	"odin.h"

struct OdinBase *OpenLibrary();
struct OdinBase *OdinBase;	/* global base pointer */

typedef struct {
	Envelope	env;	/* envelope-prefix used by odin routines */
	int		num;	/* package number */
	int		stop;	/* flag to stop consumers */
} Pack;

#define p_sizeof (long)sizeof(Pack)

typedef struct {
	Envelope	e;		/* envelope-prefix */
	char		*windowname;	/* name of windowfile to open */
} StartEnv;

#define se_sizeof (long)sizeof(StartEnv)

/*** for use around C routines that are not re-entrant ***/

struct SignalSemaphore	ss;
#define CRIT_REG(s) ObtainSemaphore(&ss); { s } ReleaseSemaphore(&ss);

/**** the body for the processes ************/

Envelope *processbody(se)
StartEnv *se;
{
	FILE *f;
	int i,stop;
	Pack *p;

	CRIT_REG(f = fopen(se->windowname,"w");)
	CRIT_REG(fprintf(f,"Hello world\n");)
	do {
		p = (Pack *)AwaitNamedEnvelope("a packet");
		stop = p->stop;
		CRIT_REG(fprintf(f,"Packet #%d received.\n",p->num);)
		DisposeEnvelope(p);
	} while(stop == 0);
	CRIT_REG(fprintf(f,"Bye, bye...\n");)
	Delay(100L);
	CRIT_REG(fclose(f);)
	return (Envelope *)se;
}

main()
{
	StartEnv *env;
	Pack *pack;
	int i;

	printf("opening library\n");
	if(!(OdinBase = OpenLibrary("ram:odin.library",0L))) {
		printf("Couldn't open odin.library\n");
		exit(20);
	}

	/* set up semaphore */
	InitSemaphore(&ss);

	/* Ought to do an AddSemaphore() here, but that doesn't work
	 * in my ROM (KS 33.180)
	 */

	printf("creating new processes\n");
	/* start first process */
	env = (StartEnv *)CreateEnvelope("newprocess1",se_sizeof);
	env->e.e_proc = processbody;
	env->windowname = "CON:10/10/300/100/Proc1";
	Eval(env,1L,4000L,EVAL_PROCESS);

	/* start next process */
	env = (StartEnv *)CreateEnvelope("newprocess2",se_sizeof);
	env->e.e_proc = processbody;
	env->windowname = "CON:310/20/300/100/Proc2";
	Eval(env,0L,4000L,EVAL_PROCESS);

	/* send some packages */
	for(i = 0; i < 10; i++) {
		pack = (Pack *)CreateEnvelope("a packet",p_sizeof);
		pack->num = i;
		pack->stop = 0;
		Out(pack);
		CRIT_REG(printf("packet #%d sent.\n",i);)
	}

	/* send the stop-packages */
	CRIT_REG(printf("sending stop-packets.\n");)
	pack = (Pack *)CreateEnvelope("a packet",p_sizeof);
	pack->stop = 1;
	Out(pack);

	pack = (Pack *)CreateEnvelope("a packet",p_sizeof);
	pack->stop = 1;
	Out(pack);

	CRIT_REG(printf("waiting for process1 to terminate\n");)
	DisposeEnvelope(AwaitNamedEnvelope("newprocess1"));
	CRIT_REG(printf("waiting for process2 to terminate\n");)
	DisposeEnvelope(AwaitNamedEnvelope("newprocess2"));

	printf("closing\n");
	CloseLibrary(OdinBase);
}

