[comp.lang.forth] Multitasking Mechanisms

rst@cs.hull.ac.uk (Rob Turner) (12/11/90)

Can anyone give me an indication of the kind of parallel
processing/coroutine mechanisms that have been implemented in various
Forths?

In the Forth implementation that I have written for the Acorn
Archimedes, I designed a coroutine kind of construct.

First of all, the user defines the Forth words he wants to execute as
coroutines. To take an overused example, let's use the four phases in
a compiler: lexical analysis, syntax analysis, semantic analysis,
and code generation.

The words which will be called as coroutines are defined thus

COROUT: LEXANALYSE
   ( ... some lexical analysis code ... )
   PAUSE
   ( ... some more lexical analysis code ... )
   PAUSE
   ( ... some more lexical analysis code ... )
COROUT;

COROUT: SYNANALYSE
   ( ... some syntactic analysis code ... )
   PAUSE
   ( ... some more syntactic analysis code ... )
COROUT;

COROUT: SEMANALYSE
   ( ... some semantic analysis code ... )
   PAUSE
   ( ... some more semantic analysis code ... )
COROUT;

COROUT: GENCODE
   ( ... some code generation code ... )
   PAUSE
   ( ... some more code generation code ... )
   PAUSE
   ( ... some more code generation code ... )
COROUT;

Next, a 'controlling' word is defined, which gives the order of
execution of the coroutines along with their computation and return
stack sizes, and, when it is called, starts the coroutines going. Thus

STARTCOROUT: COMP
   100 50 LEXANALYSE
   200 100 SYNANALYSE
   500 150 SEMANALYSE
   400 100 GENCODE
STARTCOROUT;

(I've invented the names COROUT and STARTCOROUT because I haven't
thought of a better one yet. Any offers will be appreciated).

Each coroutine has its own computation and return stack. I know this
causes difficulties passing parameters from one coroutine to another,
but it will have to be done using variables for the time being, until
I feel like modifying the execution model.

So, when word COMP is called, it starts to run coroutine LEXANALYSE,
with a computation stack size of 100 and a return stack size of 50
(the units are in 32-bit words, but that is irrelevant). LEXANALYSE
will do its stuff until it executes the word PAUSE, whereupon control
is passed to coroutine SYNANALYSE, with different computation and
return stacks, and so on. When control reaches GENCODE, and that word
executes a PAUSE, control is handed back over to LEXANALYSE, which
continues executing at the point after it previously PAUSEd. If a word
terminates execution before the others, then the coroutines are still
scheduled in a round robin fashion, but the one which has terminated
is missed out. Control will not be returned from COMP until all the
coroutines specified inside COMP have finished executing.

This method seems to work well, though the only programs I have tried
it on are fairly short tests. I have certainly not tried it on any
substantial program, so I don't know whether it is the sort of
construct which most users would find helpful or not.  Some things I
would like to know are:

What do people think of the model I have implemented? Is it useful?

What other mechanisms similar to the above have appeared in Forths,
and why are they better than mine? (I'm always optimistic :-)

I have a version of Forth for the BBC Micro which claims to perform
multitasking, but I have never got around to using it in anger, so I
don't know what mechanism/words it uses.

Thanks,

Rob