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 qîTï]QîRï]Qpî ´ïZqî –ïZî ”ïZîRîßpî ´ïV´qî{ïV´îyïV´îîPî¯ î «î#ºî%Íî(„î+‰î/Tî1 î9î=î?”îC=pî ´ïSeî 0qîpïSeînïSe pî ´ïPqî ~ïPîeïPî€îÓîî õïNo î)½î-Êî/Aî0k î7:î õïLÈî,•î0î1•î3ô î õïK î.›î0î3¥î9£î;\pî ´ïF*î î½qî uïC’î£î?îýîÕî0î Íî&{î(Hî)‘î0Sî4€ î<@î@ îGªîIÅî uïAëî<îîXîÀî"èî$˜î'¿î-î0Åî2Âî7)î<Žî?GîA¨îG‡î uï@Dî¹î†îÊîÆîŽî ¨î%,î+ˆî0²î3ˆî8êî;\î@ÇîB”îGÓî uï>œ î(î uï<îzî�îî"î ‡î#Xî$› î-kî3)î5?î8î<èî>°îAÃîEqîHCî uï:]îøî7ï5, îî1îî#ÿî&~î3wî7ï3…î£îÐîµî"�î% î0î7ï1Þ îŸîÌî±î uï/Eîèîµîî¾î¶îIî!› î+¤î.Zî1'î3…î6©î;’î?î@6îE îHîIÅî uï-ž îíî�îØî œ î)î,pî.òî0ïî4çî8áî;ýî>•î@“îC@îI5î uï+÷îî.îî–îPî…î%xî'<î-Êî2P î9mî;Øî@·îCÒîEIîIÅî uï*OîÌîšîKîWî"|î&øî(é î uï'·îØî5î€î!7 î)”î,üî.íî3Ëî:Nî>½îA×îCCîDmî uï&î.îcîpîî}î&î[îuî uï#xîbîœîŽîMîî"$î%Hî'cî-jî/-î3Òî7éî;²î>&îDzîG:î uï!Ðîjîuîv îÆîpî!°î&,î)î.Ùî0@î1eî7ãî;í îB–îD� î uï )îEîÁîî§ î%-î'Dî+Ä î4Çî8äî;¬ îC1îG†î uï‚î±îÊîKîÖî—îEî"1î uï3î3îÝî”îíî!iî#Zî(Zî,hî.»î1÷î3¦î7‘ î7ï›î¦î7ï î¹ î uïjîîÊî=î™înî"Ùî%ûî(`î-ˆ î4^î7ùî<õ îDœîHyî uïÃî uï+îôî�îî„îDî Ïî"î(¹î,åî1Ãî5u î=v îDôîGî uï ƒî¡îYîIîîîî%Ëî(Úî+9î1,î4’î7¸î9fî<‹î>9îBÊîDºîH7î uï ÜîîÀîî$îÉî Ýî#Üî&aî(çî,¢î0ìî3‡î8®î:aî@ßîCèîHî uï 5î?î¨îîZî!5î%÷î'’î)Òî+ î,cî1� î9½î<‚îBLîDÄrî)Èïöç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î uïb)î¸îÚîø îMî î"šî%´î(äî-î.# î6ñî9½î?�îBîEHî uï`‚îî7î¾î×îâîé î&Ïî*6î,¾î.Œî4ªî7>î8E î@,îB´îD‚ î7ï]çî˜î$kî)€î+ î0ëî=¹ï\@î ìïZ™ î=¹ïXñîD™î ìïWJî&xïU£î&xïSûî'Tî&xïRT î.;î/È î&xïP­î'Tî&xïOî uïG6îIîüî&îfîÆî"¿î%Îî)Ðî,0î2Bî3wî6- î7ïB îôî'Çî,Üî.gî4Gî5ùï@ZîCB î ìï>² î¦ îøî·ï= î·ï;dî$tî*gî+ó î·ï9¼î)Ëî*§î,î,ãî2¢î>î·ï8î uï5{îMî´îmîî’îýî" î&.î'¥î,ýî1Ž î7ï2àîéîdîüî_î@î$èî'¢î/;î6Óî8Bî>9îA¤îFÇîIƒî7ï19 îˆî6 î7ï.žîàîSî îhîVî%î'^î*2î,¹î.cî4sî63î8ýî>î@ŸîE,îGÉî7ï,÷îåîEî„î2î’î!Gî$î&uî,] î3 î7Zî9ºî@\îCk î7ï*]îåî\î%î„î]î!1î$˜î&÷î-šî0Qî5gî6½î8kî:Ëîøï'Âî© îkî²î"¤î$-î(ºî*î/V î6"î8ëî<›î@×îBÄîEƒîH�îøï& î'î!•î$ î)oî+¹î.}î3<î4Õî9î>Tî?îîBdîD®îøï$tî©îîÂîîòî#Iî%·î(«î)Îî, î1nî3î4: î;‹î>Œî@îA+ îIƒîøï"Ìî*îSî8î!^î#¾î(Oî+–î.Mî0î2e î;ªîB,îEøîºï 2îªî!Éî&_î1sî2Oî3*î8éîøï—î°îî÷î!%î#šî&áî(Ñî2ó î7ïýîðîÔîîóî#±î%Uî'Àî*ðî-Ê î7î;]î=Èî@¬îCBîETî7ïVîîaî3î!îî#¥î%î&óî)‡î+> î4‹î7Lî<ðî@îB}îHBî7ï® îî3îbîÍî#˜î%”î-î1 î7Vî9µî<�î?îAî7ïîÙî‚î�î î!`î%‚î'$î)xî0î2Wî8î;*î=“î@—îDlîFÀî7ïlîµ îîÕî @î#%î'Ùî*Pî.ùî1¼ î8Úî;DîAéîE~îGõî7ïÅîÞîîGîT î$Øî)Êî.¦î1Eî40 î;vî=cî@îDÔîIî7ïîî€îÀ î"×î&P î/¥î42î64î:Ìî<¡î?�îAñîG¾î7ïvî¬îÄîyîÙî î!] î*¡î-Òî0G î6.î:]î<¼î?h î7ï Üîà î îÍî#{î%Öî(©î+Êî.%î4`î7jî=HîAîD:î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ï\|îœî7ïZÔî» î7ïY- îð î7ïW†îÕî7ïUÞî… îÄïR�îÄïPèî7ïMšîý î î-îÄïJKîÄïH¤î7ïEUîsîîÉî Wî#î%±î(Ìî,¤î.iî2î3Ùî8¹î;‡î?îîA´îDkî7ïC®îÂîÄï@_îÄï>¸î7ï;iî+î’î Øî"3î(…î+Cî-Ôî0Oî5 î=oî@îA\îB·îH î7ï9ÂîBîùî9î®î!Ÿî%–î(Òî+sîÄï8îÄï6sî7ï3$î uï. î9îÓî!î#~î&Öî+!î-#î/“î2î6î<;î=úîCYî uï,hî pî uï'rqî uï$èî#îµîÿî· î uï#@î#îµîaî)îØîÜî"È î*î,Ôî uï!™î#îµ î¤î uïòî#îµ î¾îuî uïJî#îîcîK î uï£î#î î uïüî#îîcpî uïçî ìî}qî uï\îÀîkî\î†î¶î+î&Ìî,ùî56î8€î9ªî uïµ îÒî~îo î"Óî uïîî{ î4î uïf î"îŽî uï Ü î…î²î—î#î%þî2ëî5ï 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 toÿNumberSink: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î uïb! î#îPî5î"î$œî*™î3:î8·î5ï`yî$6î uï]ï î îMî2î/Kî uï[fîÛî$oî'iî0 î8 î@ î5ïY¾î5ïXî¾î@î!ˆî#´ î)ýîöïVpîæî!ˆ î*Wî.íîöïTÈî5ïS!î uïP—î7î'Ìî*ÅîöïNðî+ î4÷ î=ò îH‡î5ïMHî5ïK¡ î4 î$hî%õ î5ïIúî% îî#ôî(Šî6…î9] î5ïHRî uïEÈîD î5ïD!î5ïBz îü î5ï@Ò î1 î5ï=„ î> î%#î&°î6dî5ï;Üî¾î@î!ˆî#´î(…î+<î<î5ï:5î5ï8Žpî uï3zî?qî uï0ðî î%îbî õpî uï.fqî uï*5îøîUîhîÀî¡î!Rî%„î)Šî-Dî1­î7Ûî9Œî:¯î@…îC5îDWî7ï%!îî±îÁ î7ï"— î{îŠîøï î îcî  î' î*î,²î3'î8`î;*î>6îBîC{îøïfî°îÊî Öî"„î%Ëî) îøïÜîÐîî îÆî$áî*Dî,¤î/PîøïRî îÇîšî!‰î#0 î)]î0qî4`î5ƒî9ªî;Q îDåîøï«îXîEî7ï! î{î¡î°î!î#ýî&÷î,D îøï—îî‚î!#î$î&¾î*Fî+oî/žî3 î-î?oîB�îFÈîH�îøïAî7ï>›îîOîÚîŽî"!î%î(*î*0î,�î0ßîøï< îî?î!pî$tî'+î+dî-Ãî0±î3«î6Æî7ï9¥îèîHîˆî—î!öîøï7*îî?î àî#Ãî'Mî+î-w î4hî7î;Òî=€î?àî uï24îZî2îÕîäîDî7ï/¹î«îMîrîÒî¯î!î%îî(+î*‹î-šîøï->îéîëî bî#î%©î)·î*·î/ðî1Ìî4î8'î:÷ îA8îCn îøï+—îûîGîÝîAî!tî#Èî&Hî(9î*Žî0Ãî2¿î8oî;î>mî@îîE2îFÖîGõîøï)ðî'îÕî5î7ï'uîîìîwî,î!¿î$¸î'Èî)Îî,-î/îøï$úîî?î!pî$tî'+î+dî-Ãî2î5 î8'î:‡î=_î7ï"îîìîŸîN î7ï  î{î.îU îøï‰îîÆîuî!Ôî(wî.‰î0èî3sî5"î7�rî)ÈïýÿžTVm$ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ cofork.bravoMBrownMay 2, 1982 10:12 PM HELVETICAþ¡ TIMESROMANþŸ TIMESROMANþŸ­}tè¢j/" ™YÔ"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ cofork.press12-Jul-82 11:57:38