FILE: CoFork.mesa Last Editor: Sturgis July 23, 1981 3:32 PM
CoFork: DEFINITIONS =
BEGIN
CoForkMe: PROCEDURE RETURNS[--put-- POINTER];
END.
template for use of CoForkMe
first a few arbitrary type names, and constants
RequestType: TYPE = CARDINAL; -- any type desired
ItemType: TYPE = CARDINAL; -- any type desired
InitialParamsType: TYPE = CARDINAL; -- (can be several individual parameters, does not have to be a single parameter)
NullItem: ItemType; -- item to be returned to consumer after producer has terminated
NullRequest: RequestType; -- request to be fed to producer after consumer requests termination.
types and code associated with the producer
ItemSource: TYPE = POINTER TO PORT[RequestType] RETURNS[ItemType];
ItemSink: TYPE = POINTER TO PORT[ItemType] RETURNS[RequestType];
ItemStopper: TYPE = PROCEDURE[RequestType];
Producer:
PROCEDURE[
assortedInitialParams: InitialParamsType, -- arbitrary number
initialRequest: RequestType, -- not always needed, see example below
putItem: ItemSink] =
BEGIN
request: RequestType;
item: ItemType;
request ← putItem[item]; -- can be called at any point, and from any depth of procedure call, as many times as desired
END;
MakeProducer:
PROCEDURE[initial: InitialParamsType]
RETURNS[getItem: ItemSource, stopItems: ItemStopper] =
BEGIN
putItem: ItemSink ← CoForkMe[];
Producer[initial, putItem[NullItem], putItem];
END;
code associated with the consumer
BEGIN
initial: InitialParamsType;
getItem: ItemSource;
stopItems: ItemStopper;
item: ItemType;
request: RequestType;
[getItem, stopItems] ← MakeProducer[initial];
item ← getItem[request]; -- this call may occur as often as desired and nested to any procedure call depth.
stopItems[NullRequest]; -- it is important that this call contain NullRequest, and it is essential that getItem and stopItems not be called after this call.
END;
notes:
1) The sequence of events is as follows:
a) The Consumer calls MakeProducer.
b) MakeProducer calls CoForkMe. CoForkMe returns to MakeProducer retaining its own frame in existence.
c) MakeProducer coCalls putItem with nullItem as argument. This coCall is "captured" by CoForkMe, which preserves the argument (nullItem) for later use, and then fakes a return by MakeProducer to the Consumer.
d) The Consumer coCalls getItem with the first request. This coCall results in a coReturn to MakeProducer, delivering the first request to MakeProducer.
e) MakeProducer calls the Producer, supplying the initial arguments, the first request, as well as putItem.
f) The Producer coCalls putItem, delivering an item. This coCall results in a coReturn to the consumer with the item.
g) The Consumer coCalls getItem with a request, which results in a coReturn to the producer with the request.
h) f and g alternate until either the Producer returns to MakeProducer, or the Consumer calls stopItems.
i) If the Producer returns to MakeProducer before the Consumer calls stopItems, then MakeProducer immediately returns. This return is "captured" by CoForkMe. CoFork me now repeatedly delivers nullItem (saved from step c) to the consumer until the consumer calls stopItems.
j) If the Consumer calls stopItems before the Producer returns to MakeProducer, then CoForkMe repeatedly returns the request value delivered by the Consumer in StopItems to the Producer. This continues until the Producer returns to MakeProducer.
2) The structure of MakeProducer:
a) Any desired arguments.
b) Return parameters exactly [ItemSource, ItemStopper].
c) MakeProducer Code has following steps:
i) call CoForkMe, saving putItems.
ii) call putItems with NullItem as argument, saving the returned firstRequest.
iii) Either examine the returned firstRequest and decide whether to call the Producer, or always call the Producer with the firstRequest.
iv) RETURN
3) The structure of the Producer:
a) any desired arguments, including putItems, and possibly including firstRequest.
b) assorted coCalls on putItem, watching for nullRequest as a response suggesting that the producer return.
c) The producer may return at any time, and may continue to produce items even after receiving nullRequest.
d) no return parameters. (This is not checked, DISASTER would result.)
4) The structure of the Consumer:
a) A call on MakeProducer, saving getItem and stopItems.
b) Assorted calls on getItem, always watching for nullItem, which suggests that the producer has terminated.
c) The Consumer may continue to call getItem after receiving nullItem.
d) A call on stopItems, with nullRequest as the argument.
e) No more calls on getItem after calling stopItems. (This is not checked, DISASTER would result.)
5) The types ItemSource and ItemSink must be complementary. ItemStopper must have no result and take a RequestType as the one argument. (This is not checked, DISASTER would result.)
END.
MODULE HISTORY
Initial by: Sturgis, July 23, 1981 2:01 PM
(2048)
tedly