
/* cif-commstime-c.c -- CIF commstime */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include "cifccsp.h"

void out_string (char *str, Channel *out)
{
	unsigned char *ch = (unsigned char *)str;

	while (*ch != '\0') {
		/* ChanOut (out, ch, 1); */
		ChanOutChar (out, *ch);
		ch++;
	}
	return;
}

void proc_prefix (Process *me, int n, Channel *in, Channel *out)
{
	int i;

	ChanOutInt (out, n);
	for (;;) {
		ChanInInt (in, &i);
		ChanOutInt (out, i);
	}
	return;
}

void proc_succ (Process *me, Channel *in, Channel *out)
{
	int i;

	for (;;) {
		ChanInInt (in, &i);
		ChanOutInt (out, i+1);
	}
	return;
}

void proc_delta (Process *me, Channel *in, Channel *out1, Channel *out2)
{
	int i;

	for (;;) {
		ChanInInt (in, &i);
		ChanOutInt (out1, i);
		ChanOutInt (out2, i);
	}
	return;
}

void proc_consume (Process *me, Channel *in, Channel *kroc_err)
{
	Time t0, t1;
	int i, n;
	char str[128];

	out_string ("warming up...\n", kroc_err);
	for (i=0; i<1000; i++) {
		ChanInInt (in, &n);
	}
	out_string ("go!\n", kroc_err);
	for (;;) {
		ProcTime (&t0);
		for (i=0; i<1000000; i++) {
			ChanInInt (in, &n);
		}
		ProcTime (&t1);
		EXTERNAL_CALLN (sprintf, str, "last value: %d, comms/cxt = %d ns\n", n, (t1 - t0) / 4000);
		out_string (str, kroc_err);
	}
	return;
}

void commstime (Process *me, Channel *kroc_err)
{
	Process *pfx, *delta, *succ, *con;
	Channel a, b, c, d;

	ChanInit (&a);
	ChanInit (&b);
	ChanInit (&c);
	ChanInit (&d);

	out_string ("commstime in C.\n", kroc_err);

	pfx = ProcAlloc (proc_prefix, 4096, 3, 0, &c, &a);
	delta = ProcAlloc (proc_delta, 4096, 3, &a, &b, &d);
	succ = ProcAlloc (proc_succ, 4096, 2, &b, &c);
	con = ProcAlloc (proc_consume, 16384, 2, &d, kroc_err);

	ProcPar (pfx, delta, succ, con, NULL);

	ProcAllocClean (pfx);
	ProcAllocClean (delta);
	ProcAllocClean (succ);
	ProcAllocClean (con);
	return;
}


/* allocates process and returns address to occam world */
void real_commstime_init (int *raddr, Channel *c)
{
	Process *p = ProcAlloc (commstime, 4096, 1, c);

	*raddr = (int)p;
	return;
}

/* frees memory used by a process -- lets hope it's finished :) */
void real_commstime_free (int addr)
{
	Process *p = (Process *)addr;

	ProcAllocClean (p);
	return;
}

void _commstime_init (int *ws) { real_commstime_init ((int *)(ws[0]), (Channel *)(ws[1])); }
void _commstime_free (int *ws) { real_commstime_free ((int)(ws[0])); }

