🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.sys.transputer
1 messages
1 total messages Started by Andy Rabagliati Fri, 19 Apr 1991 15:01
Parallel programming examples - the solution - SPOILER
#1602
Author: Andy Rabagliati
Date: Fri, 19 Apr 1991 15:01
508 lines
16643 bytes
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  fifo.occ fifoc.c inout.occ makefile test1c.c test1o.occ
#   test2c.c test2o.occ
# Wrapped by andyr@inmos-c on Fri Apr 19 08:56:35 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'fifo.occ' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fifo.occ'\"
else
echo shar: Extracting \"'fifo.occ'\" \(1689 characters\)
sed "s/^X//" >'fifo.occ' <<'END_OF_FILE'
X--{{{  description of function
X-- fifo implements a true fifo - ready to input any time there is room, and
X-- ready to output any time there are characters in the buffer. Note that
X-- because we have no output ALT, this must be done with two processes.
X--
X-- input handles the resource of the buffer itself and the pointers into it,
X-- and services requests from two places. First, characters being input from
X-- in. Second, requests from the output process for new characters to
X-- output. These come in on channel signal. Responses to requests from
X-- signal go out on channel more.
X--
X-- There is no other way to handle this, given the CSP process model that the
X-- Transputer implements.
X--
X--}}}
XPROC fifo(CHAN OF BYTE in, out)
X  VAL max IS 256 :                     -- max buffer size
X  CHAN OF BOOL signal :
X  CHAN OF BYTE more :
X  PAR
X    --{{{  input process and buffer
X    [max] BYTE buffer :
X    INT the.front, back :
X    BOOL running :
X    SEQ
X      the.front, back, running := 0, 0, TRUE
X      WHILE running OR (the.front <> back)
X        INT front :
X        BOOL any :
X        SEQ
X          front := (the.front+1) \ max
X          ALT
X            (the.front <> back) & signal ? any -- signal for more
X              SEQ
X                more ! buffer [back]           -- send next
X                running := buffer[back] <> '~' -- end condition test
X                back := (back+1) \ max
X            (front <> back)     & in  ? buffer[the.front]
X              the.front := front
X    --}}}
X    --{{{  output process
X    BYTE datum :
X    SEQ
X      datum := ' '
X      WHILE datum <> '~'
X        SEQ
X          signal ! TRUE
X          more ? datum
X          out ! datum
X    --}}}
X:
END_OF_FILE
if test 1689 -ne `wc -c <'fifo.occ'`; then
    echo shar: \"'fifo.occ'\" unpacked with wrong size!
fi
# end of 'fifo.occ'
fi
if test -f 'fifoc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fifoc.c'\"
else
echo shar: Extracting \"'fifoc.c'\" \(2888 characters\)
sed "s/^X//" >'fifoc.c' <<'END_OF_FILE'
X#include <process.h>
X#define MAX 256
X#define NULL    ((void *) 0)
X
X /*
X  * fifo implements a true fifo - ready to input any time there is room, and
X  * ready to output any time there are characters in the buffer. Note that
X  * because we have no output ALT, this must be done with two processes. 
X  *
X  * input_p handles the resource of the buffer itself and the pointers into it,
X  * and services requests from two places. First, characters being input from
X  * *in. Second, requests from the process output_p for new characters to
X  * output. These come in on channel *signal. Responses to requests from
X  * signal go out on channel *more. 
X  *
X  * There is no other way to handle this, given the CSP process model that the
X  * Transputer implements. 
X  *
X  * output_p simply requests characters, then outputs them on channel *out. 
X  *
X  * Please note the way guards on ALTs are implemented. There are slightly more
X  * simple methods, but this is a very general mechanism. If the guard is
X  * false, we put the channel always_empty in the alt list. Having an empty
X  * channel means that the index returned by the ProcAltList function always
X  * corresponds to the same input being ready. Very handy. 
X  *
X  * Though in this case we will only be using always_empty in one place in the
X  * alt list, it can be put in many places. Thus if we have a 100-way guarded
X  * ALT, we only need one always_empty channel. 
X  *
X  */
X
Xvoid            input_p(Process * parent,
X	                     Channel * in, Channel * signal, Channel * more)
X{
X    Channel         always_empty;	/* remember to use & in refs */
X    Channel        *altlist[3];
X    char            buffer[MAX], lastchar = ' ';
X    int             the_front = 0, back = 0;
X    ChanInit(&always_empty);
X    altlist[2] = NULL;		/* terminator for ProcAltList */
X
X    while (lastchar != '~')
X    {
X	/* useful incremented version of the_front */
X	int             front = (the_front + 1) % MAX;
X	altlist[0] = (the_front != back) ? signal : &always_empty;
X	altlist[1] = (front != back) ? in : &always_empty;
X	switch (ProcAltList(altlist))
X	{
X	    case 0:
X		ChanInChar(signal);	/* must input signal !! */
X		ChanOutChar(more, lastchar = buffer[back++]);
X		back = back % MAX;
X		break;
X	    case 1:
X		buffer[the_front] = ChanInChar(in);
X		the_front = front;
X		break;
X	}
X    }
X}
X
Xvoid            output_p(Process * parent,
X	                    Channel * out, Channel * signal, Channel * more)
X{
X    char            c = ' ';
X    while (c != '~')
X    {
X	ChanOutChar(signal, '*');	/* anything */
X	ChanOutChar(out, c = ChanInChar(more));
X    }
X}
X
Xvoid            fifo(Process * parent, Channel * in, Channel * out)
X{
X    Channel         signal, more;
X    ChanInit(&signal);
X    ChanInit(&more);
X    ProcPar(
X	    ProcAlloc(input_p, 100, 3, in, &signal, &more),
X            ProcAlloc(output_p, 100, 3, out, &signal, &more),
X            NULL );
X}
END_OF_FILE
if test 2888 -ne `wc -c <'fifoc.c'`; then
    echo shar: \"'fifoc.c'\" unpacked with wrong size!
fi
# end of 'fifoc.c'
fi
if test -f 'inout.occ' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'inout.occ'\"
else
echo shar: Extracting \"'inout.occ'\" \(2002 characters\)
sed "s/^X//" >'inout.occ' <<'END_OF_FILE'
X-- The iserver routines can easily be replaced by similar ones in the hostio
X-- library. I just like to know exactly what is going on - this way nothing
X-- goes on the Transputer that I dont know about.
X-- This applies to write.char, pollkey, and so.exit.
X
XPROTOCOL SP IS INT16::[]BYTE :
X--{{{  PROC inout(CHAN OF SP fs, ts, CHAN OF BYTE out, in)
XPROC inout(CHAN OF SP fs, ts, CHAN OF BYTE out, in)
X  -- routines similar to these are in hostio.lib
X  --{{{  PROC write.char (VAL BYTE char)
X  PROC write.char (VAL BYTE char)
X    SEQ
X      ts ! 8(INT16)::[24(BYTE),                 -- length, FPutBlock
X            1(BYTE), 0(BYTE), 0(BYTE), 0(BYTE), -- StreamId = 1
X            1(BYTE), 0(BYTE),                   -- INT16 len = 1
X            char ]
X      INT16 len :
X      [8]BYTE packet :
X      fs ? len::packet
X  :
X  --}}}
X  --{{{  PROC pollkey(BYTE char, BYTE result)
X  PROC pollkey(BYTE char, BYTE result)
X    INT16 len :
X    [8]BYTE packet :
X    SEQ
X      ts ! 8(INT16)::[31(BYTE),             -- length, Pollkey
X            'x','x','x','x','x','x','x']    -- padding to 8 bytes
X      fs ? len::packet                      -- read result
X      char, result := packet[1], packet[0]
X  :
X  --}}}
X  BYTE char :
X  SEQ
X    char := ' '
X    WHILE char <> '~'
X      TIMER TIME :
X      INT now :
X      SEQ
X        TIME ? now
X        ALT
X          in ? char
X            write.char(char)
X          TIME ? AFTER now PLUS 156  -- 1/100 sec
X            BYTE key, result :
X            SEQ
X              pollkey(key, result)
X              IF
X                result = 0(BYTE)
X                  out ! (BYTE key)
X                TRUE
X                  SKIP
X:
X--}}}
X--{{{  PROC so.exit(CHAN OF SP fs, ts)
XPROC so.exit(CHAN OF SP fs, ts)
X  SEQ
X    ts ! 8(INT16)::[35(BYTE),                         -- length, Exit
X          #FF(BYTE), #C9(BYTE), #9A(BYTE), #3B(BYTE), -- Success 999999999
X          'x','x','x']                                -- padding
X    INT16 len :
X    [8]BYTE packet :
X    fs ? len::packet
X:
X--}}}
END_OF_FILE
if test 2002 -ne `wc -c <'inout.occ'`; then
    echo shar: \"'inout.occ'\" unpacked with wrong size!
fi
# end of 'inout.occ'
fi
if test -f 'makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile'\"
else
echo shar: Extracting \"'makefile'\" \(1423 characters\)
sed "s/^X//" >'makefile' <<'END_OF_FILE'
XOCCOPT=  /y /t8
XLINKOPT= /y /t8
XCONFOPT=
XOCONFOPT=
XCOLLECTOPT= /t
XCOPT= /t8
X
Xtest2c:     test2c.btl
X            iserver /se /sb test2c.btl
X
Xtest2c.btl: test2c.lku
X            icollect $(COLLECTOPT) test2c.lku
X
Xtest2c.lku: test2c.tco fifoc.tco
X            ilink $(LINKOPT) test2c.tco fifoc.tco libc.lib centry.lib /me C.ENTRY
X
Xtest2c.tco: test2c.c
X            icc $(COPT) test2c.c
X
Xfifoc.tco:  fifoc.c
X            icc $(COPT) fifoc.c
X
Xtest1c:     test1c.btl
X            iserver /se /sb test1c.btl
X
Xtest1c.btl: test1c.lku
X            icollect $(COLLECTOPT) test1c.lku
X
Xtest1c.lku: test1c.tco
X            ilink $(LINKOPT) test1c.tco libc.lib centry.lib /me C.ENTRY
X
Xtest1c.tco: test1c.c
X            icc $(COPT) test1c.c
X
Xtest2o:     test2o.btl
X            iserver /se /sb test2o.btl
X
Xtest2o.btl: test2o.lku
X            icollect $(COLLECTOPT) test2o.lku
X
Xtest2o.lku: test2o.tco inout.tco fifo.tco
X            ilink $(LINKOPT) test2o.tco inout.tco fifo.tco
X
Xtest2o.tco: test2o.occ inout.tco fifo.tco
X            oc $(OCCOPT) test2o.occ
X
Xtest1o:     test1o.btl
X            iserver /se /sb test1o.btl
X
Xtest1o.btl: test1o.lku
X            icollect $(COLLECTOPT) test1o.lku
X
Xtest1o.lku: test1o.tco
X            ilink $(LINKOPT) test1o.tco inout.tco
X
Xtest1o.tco: test1o.occ inout.tco
X            oc $(OCCOPT) test1o.occ
X
Xinout.tco:  inout.occ
X            oc $(OCCOPT) inout.occ
X
Xfifo.tco:   fifo.occ
X            oc $(OCCOPT) fifo.occ
X
END_OF_FILE
if test 1423 -ne `wc -c <'makefile'`; then
    echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
if test -f 'test1c.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'test1c.c'\"
else
echo shar: Extracting \"'test1c.c'\" \(1905 characters\)
sed "s/^X//" >'test1c.c' <<'END_OF_FILE'
X#include <process.h>
X#include <stdio.h>
X#include <iocntrl.h>
X
X#define MAX 100
X
Xvoid buf (Process *parent, Channel *in, Channel *out) {
X    char c = ' ';
X    while (c!='~')
X        ChanOutChar(out, c=ChanInChar(in));
X}
X
Xvoid buffer (Process *parent, Channel *in, Channel *out) {
X    Channel pipe[MAX];          /* we are declaring the channels themselves,
X                                 * so remember to use & address-of */
X    Process *list[MAX+2];       /* will be MAX+1 processes */
X    int i;
X
X    for (i=0; i < (MAX-1); i++) {
X        ChanInit(&pipe[i]);                 /* clear channel */
X        list[i] = ProcAlloc(buf, 80, 2, &pipe[i], &pipe[i+1]);
X                                            /* 80 bytes seems to be enough */
X    }
X    ChanInit(&pipe[MAX-1]);           /* last pipe - not hit by loop above */
X
X    list[MAX-1] = ProcAlloc(buf, 80, 2, in, &pipe[0]);
X    list[MAX]   = ProcAlloc(buf, 80, 2, &pipe[MAX-1], out);
X    list[MAX+1] = NULL;              /* end of list for ProcParList */
X
X    ProcParList(list);
X}
X
Xvoid inout(Process *parent, Channel *out, Channel *in) {
X    int key;
X    char c = ' ';
X    while (c!='~') {
X        switch (ProcTimerAlt(ProcTimePlus(ProcTime(), 156), in, NULL)) {
X            case -1:
X                key = pollkey();
X                if (key != -1)
X                    ChanOutChar(out, (char) key);
X                break;
X            case 0:
X                putchar(c = ChanInChar(in));
X                fflush(stdout);
X                break;
X        }
X    }
X}
X
Xint main(void) {
X    Channel to_buf, from_buf;   /* we are declaring the channels themselves,
X                                 * so remember to use & address-of */
X    ChanInit(&to_buf);
X    ChanInit(&from_buf);
X    ProcPar(
X        ProcAlloc(inout, 4096, 2, &to_buf, &from_buf),
X        ProcAlloc(buffer, 4096, 2, &to_buf, &from_buf), NULL );
X
X    return (999999999);     /* success */
X}
X
END_OF_FILE
if test 1905 -ne `wc -c <'test1c.c'`; then
    echo shar: \"'test1c.c'\" unpacked with wrong size!
fi
# end of 'test1c.c'
fi
if test -f 'test1o.occ' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'test1o.occ'\"
else
echo shar: Extracting \"'test1o.occ'\" \(458 characters\)
sed "s/^X//" >'test1o.occ' <<'END_OF_FILE'
XPROTOCOL SP IS INT16::[]BYTE :
X#USE "inout.tco"
XPROC exercise1(CHAN OF SP fs, ts, []INT memory)
X  SEQ
X    VAL MAX IS 10 :
X    [MAX+1]CHAN OF BYTE pipe :
X    PAR
X      inout(fs, ts, pipe[0], pipe[MAX])
X      PAR i = 0 FOR MAX
X        --{{{  little buffer processes
X        BYTE char :
X        SEQ
X          char := ' '
X          WHILE char <> '~'
X            SEQ
X              pipe[i] ? char
X              pipe[i+1] ! char
X        --}}}
X    so.exit(fs, ts)
X:
END_OF_FILE
if test 458 -ne `wc -c <'test1o.occ'`; then
    echo shar: \"'test1o.occ'\" unpacked with wrong size!
fi
# end of 'test1o.occ'
fi
if test -f 'test2c.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'test2c.c'\"
else
echo shar: Extracting \"'test2c.c'\" \(1301 characters\)
sed "s/^X//" >'test2c.c' <<'END_OF_FILE'
X#include <process.h>
X#include <stdio.h>
X#include <iocntrl.h>
X
Xvoid            fifo(Process *, Channel *, Channel *, Channel *);
X
X /*
X  * inout is functionally equivalent to two parallel processes, one taking
X  * keys from the keyboard and outputting them to *out, the other reading
X  * characters from *in and writing them to the screen. It is in fact
X  * implemented as an ALT, because both pseudo-processes need both iserver
X  * channels. 
X  */
X
Xvoid            inout(Process * parent, Channel * out, Channel * in)
X{
X    int             key;
X    char            c = ' ';
X    while (c != '~')
X    {
X	switch (ProcTimerAlt(ProcTimePlus(ProcTime(), 156), in, NULL))
X	{
X	    case -1:		/* timeout - poll keyboard */
X		key = pollkey();
X		if (key != -1)
X		    ChanOutChar(out, (char) key);
X		break;
X	    case 0:		/* in is ready - read it */
X		putchar(c = ChanInChar(in));
X		fflush(stdout);
X		break;
X	}
X    }
X}
X
Xint             main(void)
X{
X    Channel         to_buf, from_buf;	/* we are declaring the channels
X					 * themselves, so remember to use &
X					 * address-of */
X    ChanInit(&to_buf);
X    ChanInit(&from_buf);
X    ProcPar(
X	    ProcAlloc(inout, 4096, 2, &to_buf, &from_buf),
X            ProcAlloc(fifo, 4096, 2, &to_buf, &from_buf),
X            NULL );
X
X    return (999999999);		/* success */
X}
END_OF_FILE
if test 1301 -ne `wc -c <'test2c.c'`; then
    echo shar: \"'test2c.c'\" unpacked with wrong size!
fi
# end of 'test2c.c'
fi
if test -f 'test2o.occ' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'test2o.occ'\"
else
echo shar: Extracting \"'test2o.occ'\" \(251 characters\)
sed "s/^X//" >'test2o.occ' <<'END_OF_FILE'
XPROTOCOL SP IS INT16::[]BYTE :
X#USE "inout.tco"
X#USE "fifo.tco"
XPROC exercise2(CHAN OF SP fs, ts, []INT memory)
X  SEQ
X    CHAN OF BYTE to.buf, from.buf :
X    PAR
X      inout(fs, ts, to.buf, from.buf)
X      fifo(to.buf, from.buf)
X    so.exit(fs, ts)
X:
END_OF_FILE
if test 251 -ne `wc -c <'test2o.occ'`; then
    echo shar: \"'test2o.occ'\" unpacked with wrong size!
fi
# end of 'test2o.occ'
fi
echo shar: End of shell archive.
exit 0
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads