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