Name:CoForkMaintainer:SturgisDate:August7,1981Purpose:ProvidesfortheconvenientstartupandshutdownofCo-RoutineswhichuseMesaPORTS.Filedas:CoFork.BravoFiles:Thereare3files:CoFork.mesa,.bcd--adefinitionsfileCoForkImpl.mesa,.bcd--theimplementationCoForkDemo.mesa--someexamplesofuseHowtouse:YoushouldthinkofyourmainprogramasaConsumerwhich"consumes"items"produced"byaProducer.TheconsumerfromtimetotimerequestsitemsbycallinggetItem,andtheproducerfromtimetotimeproducesitemsbycallingputItem.getItemandputItemarepointerstoPORTSwithcomplementarytype.BeginbydefininganItemTypeandaRequestType,followedbytwopointertoporttypesandoneproceduretype:ItemSource:TYPE=POINTERTOPORT[RequestType]RETURNS[ItemType];ItemSink:TYPE=POINTERTOPORT[ItemType]RETURNS[RequestType];ItemStopper:TYPE=PROCEDURE[RequestType];Noticethatthetwoporttypesarecomplementary,andthattheitemstoppertakesarequesttypeasaparameter.Also,ItemTypeandRequestTypeneednotbesingletypes,theycanbeanysequenceoftypeswhichcouldappearasasequenceofparametertypes.FrequentlytherequesttypeissimplyaBooleanthatindicatesanotheritemshouldbedelivered.WARNING:BothItemTypeandRequestTypemustbe"short"parametertypes.Thisisamaximumof5wordsintheMesa6Altoimplementation.TheitemproducerwillmakeportcallsonItemSinktodeliveritems,whiletheconsumerwillmakeportcallsonItemSourcetoobtainitems.Theproducerisaprocedurewhichterminatesbyreturning,whiletheconsumersignalsterminationbycallingItemStopper.Thesetwoterminationeventsmustbothoccur,butcanoccurineitherorder.Specialitemsandrequestsshouldbedefinedwhichareusedtosignaltermination.NullItem:ItemType;NullRequest:RequestType;(Ofcourse,ifItemTypeorRequesttypeareactuallysequences,thesespecificdeclarationscouldnotoccur)Nowwritetheproducer;thisisaprocedurewhichacceptssomeinitializationparameters,aninitialrequest,andanItemSink.TheproducercallstheItemSinkfromtimetotimetodeliveranitem,andtoreceivethenextrequest.ThisPortcallcanoccurnestedanynumberofprocedurecallsdeep.Theproducershouldexaminethenewrequesttoseeifitsuggeststermination.Theproducercanterminate1p `q 0`.`p ]Q qT]QR]Qp Zq Z ZRp Vq{VyVP #%(+/T1 9=?C=p Se 0qpSenSe p Pq ~PeP No )-/A0k 7: L,013 K .039;\p F* q uC?0 &{(H)0S4 <@@ GI uA<X"$'-027)<?GAG u@D %,+038;\@BG u> ( u<z" #X$ -k3)5?8<>AEqHC u:]75, 1#&~3w73"% 071  u/EI! +.Z1'36;?@6E HI u-  ),p.048;>@C@I5 u+.P%x'<-2P 9m;@CEII u*OKW"|&( u'5!7 ),.3:N>ACCDm u&.cp}&[u u#xbM"$%H'c-j/-37;>&DzG: u!juv p!&,).0@1e7; BD u )E %-'D+ 48; C1G uKE"1 u33!i#Z(Z,h.137 77  uj=n"%(`- 4^7< DHy u u+D "(,15u =v DG u YI%(+91,479f<>9BDH7 u $ #&a(,038:a@CH u 5?Z!5%')+ ,c1 9<BLDr)TVm$^ Producer, the user next writes the following 6 line procedure:MakeProducer: PROCEDURE[param1: Initial1, ... paramN: InitialN]RETURNS[getItem: ItemSource, stopItems: ItemStopper] =BEGINputItem: ItemSink _ CoForkMe[];Producer[param1, . . , paramN, putItem[nullItem], putItem];END; The form of this procedure is very rigid. It peforms several funbeforeseeingaNullRequest,oranytimeafterseeingaNullRequest.TheproducercanevencontinuetoproduceitemsafterseeingaNullRequest(theywillbeabsorbed,andaNullRequestwillbereturned).Producer:PROCEDURE[param1:Initial1,...paramN:InitialN,initialrequest:RequestType,putItem:ItemSink]=BEGIN..newRequest_putItem[item];..END;HavingwrittenaProducer,theusernextwritesthefollowing6lineprocedure:MakeProducer:PROCEDURE[param1:Initial1,...paramN:InitialN]RETURNS[getItem:ItemSource,stopItems:ItemStopper]=BEGINputItem:ItemSink_CoForkMe[];Producer[param1,..,paramN,putItem[nullItem],putItem];END;Theformofthisprocedureisveryrigid.Itpeformsseveralfunctions:1)ItstartstheproducercoRoutine(viaCoForkMe)(CoForkMeisimportedfromCoForkandisimplementedinCoForkImpl).2)ItdefinesthenullItem,(throughthefirstcalltoputItem),sothatCoForkcandeliverthisitemtotheconsumerintheeventthattheProducerterminatesbeforetheConsumercallsstopItems.3)ItobtainsthefirstrequestfromtheConsumeranddeliversittotheProducer.note:frequentlyarequestissimplyabooleanrequestingonemoreitem.InthiscasetheMakeProducerprocedurecanexaminethefirstrequesttodecidewhethertocalltheProducer,andifsotheproducerneednottakeafirstrequestasaparameter.e.g.IfaRequestTypeissuchaBOOLEAN,thenthesecondcodelineoftheMakeProducerprocedurecouldbe:IFputItem[nullItem]THENProducer[param1,..paramN,putItem];andtheProducerwouldnothavean"initialRequest"parameter.4)TheconsumerobtainscontrolatthetimethatMakeProducermakesthefirstcallonputItem.TheconsumerobtainscontrolasifitscalltoMakeProducerhadreturnedwiththeexpectedtwoparameters.ThisreturnisfakedbyCoForkMe,whichinterceptsthefirstcallonputItem.5)SinceCoForkMefakesthereturntotheconsumer,thecompilerdoesnottypecheckthereturnfromMakeProducertoseethatexactlythecorrecttwoparametersarereturned.ThustheusermustbesurethatMakeProducerreturnsexactlythetwoparametersinthecorrectorder.Inaddition,thereturnparametersfromMakeProducershouldbenamedsothatthecompilerdoesnotobjectwhenthecodeforMakeProducerdoesnotexplicitlyreturnthetwoparameters.6)MakeProducerregainscontrolthefirsttimetheconsumercallsgetItem.Fromthenoncontrolalternatesbetweentheconsumerandtheproducer.2q ub) M "%(-.# 69?BEH u`7 &*6,.47>8E @,BD 7]$k)+ 0=\@ Z =XD WJ&xU&xS'T&xRT .;/ &xP'T&xO uG6I&f"%),02B3w6- 7B ',.g4G5@ZCB >  = ;d$t*g+ 9)*,,2>8 u5{Mm" &.',1 72d_@$'/;68B>9AFI719 6 7.S hV%'^*2,.c4s638>@E,G7,E2!G$&u,] 3 7Z9@\Ck 7*]\%]!1$&-0Q5g68k:' k"$-(*/V 6"8<@BEH& '!$ )o+.}3<49>T?BdD$t#I%(),1n34: ;>@A+ I"*S8!^#(O+.M02e ;B,E 2!&_1s2O3*8!%#&(2 7#%U'*- 7;]=@CBET7Va3!#%&)+> 47L<@B}HB7 3b#%-1 7V9<?A7 !`%'$)x02W8;*=@DlF7l  @#%'*P.1 8;DAE~G7GT $).1E40 ;v=c@DI7 "&P /4264:<?AG7vy !] *-0G 6.:]<?h 7   #{%(+.%4`7j=HAD:F<7 5 a/#o&&(r)HTVm$^FinallywritetheConsumerwiththefollowinggeneralform:BEGINinitial:InitialParamsType;getItem:ItemSource;stopItems:ItemStopper;item:ItemType;request:RequestType;----[getItem,stopItems]_MakeProducer[initial];----item_getItem[request];--thiscallmayoccurasoftenasdesiredandnestedtoanyprocedurecalldepth.----stopItems[NullRequest];--itisimportantthatthiscallcontainNullRequest,anditisessentialthatgetItemandstopItemsnotbecalledafterthiscall.----END;RESTRICTION:OncestopItemshasbeencalled,donotcalleitherstopItemsorgetItem,DISASTERwillresult.Review:1)DefineItemTypeandRequestType.2)DefinetwopointertoPorttypes,ItemSourceandItemSink.3)DefineItemStoppertype.4)DefineNullRequestandNullItem.5)WritetheProducerprocedure.6)WriteMakeProducer.7)WritetheConsumer.ASimpleExample:ItemTypewillbeapair,(NotaRECORD).RequestTypewillbe.nullItemis.nullRequestisFALSE.NumberSource:TYPE=POINTERTOPORT[moreWanted:BOOLEAN]RETURNS[n:CARDINAL,nIsNull:BOOLEAN];3q u`' #!)3.7^#7\|7Z 7Y-  7W7U RP7M -JKH7EUs W#%(,.i238;?ADk7C@_>7;i+ "3(+C-0O5 =o@A\BH 79B9!%(+s86s73$ u. 9!#~&+!-#/26<;=CY u,h p u'rq u$# u#@#a)" *, u!#  u# u uJ#cK u# u#cp u }q u\k\+&,5689 u ~o " u{ 4 uf " u #%25 5 F%+dr)TVm$em).CoForkMe captures this call, and fakes a return from MakeProducer to theConsumer. This faked return returns the source port and the stopper procedure toNumberSink:TYPE=POINTERTOPORT[n:CARDINAL,nIsNull:BOOLEAN]RETURNS[moreWanted:BOOLEAN];NumberStopper:TYPE=PROCEDURE[moreWanted:BOOLEAN];NumberProducer:PROCEDURE[first,last:CARDINAL,putNumber:NumberSink]=BEGINFORI:CARDINALIN[first..last]DOIFNOTputNumber[I]THENEXIT;ENDLOOP;END;MakeNumberProducer:PROCEDURE[first,last:CARDINAL]RETURNS[getNumber:NumberSource,stopNumbers:NumberStopper]=BEGINputNumber:NumberSink_CoForkMe[];IFputNumber[0,TRUE]THENNumberProducer[first,last,putNumber];END;MainCode(Consumer)BEGINgetNumber:NumberSource;stopNumbers:NumberStopper;[getNumber,stopNumbers]_MakeNumberProducer[5,25];FORI:CARDINALIN[0..100)DOPrint[getNumber[TRUE].n]ENDLOOP;stopNumbers[FALSE];END;MoreExamples:SeeCoForkDemo.mesaformoreexamples.ExecutionWedescribeherethesequenceofeventswhichoccurduringexecutionofaproducerandaconsumer.TheConsumercallsMakeProducerMakeProducercallsCoForkMeCoForkMeconstructsaco-routinewithtwoprocedureframes.ThebaseframeisCoForkMe,andCoForkMeappearstohavecalledMakeProducer.ThelocalframeofCoForkMecontainsthetwoports.Whileretainingitsframeinexistence,CoForkMetfakesareturntoMakeProducer,returningthesinkport.MakeProducerthencallsthesinkport(passingnullItem).CoForkMecapturesthiscall,andfakesareturnfromMakeProducertotheConsumer.ThisfakedreturnreturnsthesourceportandthestopperproceduretotheConsumer.TheCoRoutinecontinuesinexistencewiththetwoframesasdescribedabove.TheConsumercallsthesourceport(withthefirstrequest).ThisisaportcallresultinginaportreturntoMakeProducer(fromitscallonthesinkport),4q ub! #P5"$*3:85`y$6 u]  M2/K u[f$o'i0 8 @5Y5X@!# )Vp! *W.T5S! uP7'*N+ 4 = H5MH5K 4 $h% 5I% #(69] 5HR uED 5D!5Bz  5@ 1 5= > %#&6d5;@!#(+<<5:558p u3z?q u0 %b p u.fq u*5Uh!R%)-D179:@C5DW7%! 7" {  c  ' *,3'8`;*>6BC{f "%)  $*D,/PR !#0 )]0q4`59;Q DXE7! {!#&,D !#$&*F+o/3 -?oBFHA7>O"!%(**0,0< ?!p$t'++d-03679H!7*? #'M+-w 4h7;=? u24Z2D7/Mr!%(+*--> b#%)*/148': A8Cn +GA!t#&H(9*028o;>m@E2FG)'57'uw,!$'),-/$?!p$t'++d-25 8':=_7"N 7  {.U u!(w.03s5"7r)TVm$ cofork.bravoMBrownMay 2, 1982 10:12 PM HELVETICA TIMESROMAN TIMESROMAN}tj/" Y" cofork.press12-Jul-82 11:57:38