fibers.xml 1.2 MB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
  3. <library id="fiber" name="Fiber" dirname="fiber" last-revision="$Date: 2018/10/22 08:13:04 $"
  4. xmlns:xi="http://www.w3.org/2001/XInclude">
  5. <libraryinfo>
  6. <authorgroup>
  7. <author>
  8. <firstname>Oliver</firstname> <surname>Kowalke</surname>
  9. </author>
  10. </authorgroup>
  11. <copyright>
  12. <year>2013</year> <holder>Oliver Kowalke</holder>
  13. </copyright>
  14. <legalnotice id="fiber.legal">
  15. <para>
  16. Distributed under the Boost Software License, Version 1.0. (See accompanying
  17. file LICENSE_1_0.txt or copy at <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
  18. </para>
  19. </legalnotice>
  20. <librarypurpose>
  21. C++ Library to cooperatively schedule and synchronize micro-threads
  22. </librarypurpose>
  23. <librarycategory name="category:text"></librarycategory>
  24. </libraryinfo>
  25. <title>Fiber</title>
  26. <section id="fiber.overview">
  27. <title><link linkend="fiber.overview">Overview</link></title>
  28. <para>
  29. <emphasis role="bold">Boost.Fiber</emphasis> provides a framework for micro-/userland-threads
  30. (fibers) scheduled cooperatively. The API contains classes and functions to
  31. manage and synchronize fibers similiarly to <ulink url="http://en.cppreference.com/w/cpp/thread">standard
  32. thread support library</ulink>.
  33. </para>
  34. <para>
  35. Each fiber has its own stack.
  36. </para>
  37. <para>
  38. A fiber can save the current execution state, including all registers and CPU
  39. flags, the instruction pointer, and the stack pointer and later restore this
  40. state. The idea is to have multiple execution paths running on a single thread
  41. using cooperative scheduling (versus threads, which are preemptively scheduled).
  42. The running fiber decides explicitly when it should yield to allow another
  43. fiber to run (context switching). <emphasis role="bold">Boost.Fiber</emphasis>
  44. internally uses <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink>
  45. from <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>;
  46. the classes in this library manage, schedule and, when needed, synchronize
  47. those execution contexts. A context switch between threads usually costs thousands
  48. of CPU cycles on x86, compared to a fiber switch with less than a hundred cycles.
  49. A fiber runs on a single thread at any point in time.
  50. </para>
  51. <para>
  52. In order to use the classes and functions described here, you can either include
  53. the specific headers specified by the descriptions of each class or function,
  54. or include the master library header:
  55. </para>
  56. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">all</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  57. </programlisting>
  58. <para>
  59. which includes all the other headers in turn.
  60. </para>
  61. <para>
  62. The namespaces used are:
  63. </para>
  64. <programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase>
  65. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase>
  66. </programlisting>
  67. <bridgehead renderas="sect3" id="fiber.overview.h0">
  68. <phrase id="fiber.overview.fibers_and_threads"/><link linkend="fiber.overview.fibers_and_threads">Fibers
  69. and Threads</link>
  70. </bridgehead>
  71. <para>
  72. Control is cooperatively passed between fibers launched on a given thread.
  73. At a given moment, on a given thread, at most one fiber is running.
  74. </para>
  75. <para>
  76. Spawning additional fibers on a given thread does not distribute your program
  77. across more hardware cores, though it can make more effective use of the core
  78. on which it's running.
  79. </para>
  80. <para>
  81. On the other hand, a fiber may safely access any resource exclusively owned
  82. by its parent thread without explicitly needing to defend that resource against
  83. concurrent access by other fibers on the same thread. You are already guaranteed
  84. that no other fiber on that thread is concurrently touching that resource.
  85. This can be particularly important when introducing concurrency in legacy code.
  86. You can safely spawn fibers running old code, using asynchronous I/O to interleave
  87. execution.
  88. </para>
  89. <para>
  90. In effect, fibers provide a natural way to organize concurrent code based on
  91. asynchronous I/O. Instead of chaining together completion handlers, code running
  92. on a fiber can make what looks like a normal blocking function call. That call
  93. can cheaply suspend the calling fiber, allowing other fibers on the same thread
  94. to run. When the operation has completed, the suspended fiber resumes, without
  95. having to explicitly save or restore its state. Its local stack variables persist
  96. across the call.
  97. </para>
  98. <para>
  99. A fiber can be migrated from one thread to another, though the library does
  100. not do this by default. It is possible for you to supply a custom scheduler
  101. that migrates fibers between threads. You may specify custom fiber properties
  102. to help your scheduler decide which fibers are permitted to migrate. Please
  103. see <link linkend="migration">Migrating fibers between threads</link> and
  104. <link linkend="custom">Customization</link> for more details.
  105. </para>
  106. <para>
  107. <emphasis role="bold">Boost.Fiber</emphasis> allows to <emphasis role="bold"><code><phrase
  108. role="identifier">multiplex</phrase> <phrase role="identifier">fibers</phrase>
  109. <phrase role="identifier">across</phrase> <phrase role="identifier">multiple</phrase>
  110. <phrase role="identifier">cores</phrase></code></emphasis> (see <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link>).
  111. </para>
  112. <para>
  113. A fiber launched on a particular thread continues running on that thread unless
  114. migrated. It might be unblocked (see <link linkend="blocking">Blocking</link>
  115. below) by some other thread, but that only transitions the fiber from <quote>blocked</quote>
  116. to <quote>ready</quote> on its current thread &mdash; it does not cause the fiber to
  117. resume on the thread that unblocked it.
  118. </para>
  119. <anchor id="thread_local_storage"/>
  120. <bridgehead renderas="sect3" id="fiber.overview.h1">
  121. <phrase id="fiber.overview.thread_local_storage"/><link linkend="fiber.overview.thread_local_storage">thread-local
  122. storage</link>
  123. </bridgehead>
  124. <para>
  125. Unless migrated, a fiber may access thread-local storage; however that storage
  126. will be shared among all fibers running on the same thread. For fiber-local
  127. storage, please see <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link>.
  128. </para>
  129. <anchor id="cross_thread_sync"/>
  130. <bridgehead renderas="sect3" id="fiber.overview.h2">
  131. <phrase id="fiber.overview.boost_fibers_no_atomics"/><link linkend="fiber.overview.boost_fibers_no_atomics">BOOST_FIBERS_NO_ATOMICS</link>
  132. </bridgehead>
  133. <para>
  134. The fiber synchronization objects provided by this library will, by default,
  135. safely synchronize fibers running on different threads. However, this level
  136. of synchronization can be removed (for performance) by building the library
  137. with <emphasis role="bold"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></emphasis>
  138. defined. When the library is built with that macro, you must ensure that all
  139. the fibers referencing a particular synchronization object are running in the
  140. same thread. Please see <link linkend="synchronization">Synchronization</link>.
  141. </para>
  142. <anchor id="blocking"/>
  143. <bridgehead renderas="sect3" id="fiber.overview.h3">
  144. <phrase id="fiber.overview.blocking"/><link linkend="fiber.overview.blocking">Blocking</link>
  145. </bridgehead>
  146. <para>
  147. Normally, when this documentation states that a particular fiber <emphasis>blocks</emphasis>
  148. (or equivalently, <emphasis>suspends),</emphasis> it means that it yields control,
  149. allowing other fibers on the same thread to run. The synchronization mechanisms
  150. provided by <emphasis role="bold">Boost.Fiber</emphasis> have this behavior.
  151. </para>
  152. <para>
  153. A fiber may, of course, use normal thread synchronization mechanisms; however
  154. a fiber that invokes any of these mechanisms will block its entire thread,
  155. preventing any other fiber from running on that thread in the meantime. For
  156. instance, when a fiber wants to wait for a value from another fiber in the
  157. same thread, using <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  158. role="identifier">future</phrase></code> would be unfortunate: <code><phrase
  159. role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase
  160. role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
  161. would block the whole thread, preventing the other fiber from delivering its
  162. value. Use <link linkend="class_future"><code>future&lt;&gt;</code></link> instead.
  163. </para>
  164. <para>
  165. Similarly, a fiber that invokes a normal blocking I/O operation will block
  166. its entire thread. Fiber authors are encouraged to consistently use asynchronous
  167. I/O. <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
  168. and other asynchronous I/O operations can straightforwardly be adapted for
  169. <emphasis role="bold">Boost.Fiber</emphasis>: see <link linkend="callbacks">Integrating
  170. Fibers with Asynchronous Callbacks</link>.
  171. </para>
  172. <para>
  173. <emphasis role="bold">Boost.Fiber</emphasis> depends upon <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>.
  174. Boost version 1.61.0 or greater is required.
  175. </para>
  176. <note>
  177. <para>
  178. This library requires C++11!
  179. </para>
  180. </note>
  181. <section id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber">
  182. <title><anchor id="implementation"/><link linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber">Implementations:
  183. fcontext_t, ucontext_t and WinFiber</link></title>
  184. <para>
  185. <emphasis role="bold">Boost.Fiber</emphasis> uses <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink>
  186. from <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>
  187. as building-block.
  188. </para>
  189. <bridgehead renderas="sect4" id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.h0">
  190. <phrase id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.fcontext_t"/><link
  191. linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.fcontext_t">fcontext_t</link>
  192. </bridgehead>
  193. <para>
  194. The implementation uses <code><phrase role="identifier">fcontext_t</phrase></code>
  195. per default. fcontext_t is based on assembler and not available for all platforms.
  196. It provides a much better performance than <code><phrase role="identifier">ucontext_t</phrase></code>
  197. (the context switch takes two magnitudes of order less CPU cycles; see section
  198. <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/performance.html"><emphasis>performance</emphasis></ulink>)
  199. and <code><phrase role="identifier">WinFiber</phrase></code>.
  200. </para>
  201. <bridgehead renderas="sect4" id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.h1">
  202. <phrase id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.ucontext_t"/><link
  203. linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.ucontext_t">ucontext_t</link>
  204. </bridgehead>
  205. <para>
  206. As an alternative, <ulink url="https://en.wikipedia.org/wiki/Setcontext"><code><phrase
  207. role="identifier">ucontext_t</phrase></code></ulink> can be used by compiling
  208. with <code><phrase role="identifier">BOOST_USE_UCONTEXT</phrase></code> and
  209. b2 property <code><phrase role="identifier">context</phrase><phrase role="special">-</phrase><phrase
  210. role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">ucontext</phrase></code>.
  211. <code><phrase role="identifier">ucontext_t</phrase></code> might be available
  212. on a broader range of POSIX-platforms but has some <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/rational.html#ucontext"><emphasis>disadvantages</emphasis></ulink>
  213. (for instance deprecated since POSIX.1-2003, not C99 conform).
  214. </para>
  215. <note>
  216. <para>
  217. <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink>
  218. supports <link linkend="segmented"><emphasis>Segmented stacks</emphasis></link>
  219. only with <code><phrase role="identifier">ucontext_t</phrase></code> as
  220. its implementation.
  221. </para>
  222. </note>
  223. <bridgehead renderas="sect4" id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.h2">
  224. <phrase id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.winfiber"/><link
  225. linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.winfiber">WinFiber</link>
  226. </bridgehead>
  227. <para>
  228. With <code><phrase role="identifier">BOOST_USE_WINFIB</phrase></code> and
  229. b2 property <code><phrase role="identifier">context</phrase><phrase role="special">-</phrase><phrase
  230. role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">winfib</phrase></code>
  231. Win32-Fibers are used as implementation for <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink>.
  232. </para>
  233. <para>
  234. Because the TIB (thread information block) is not fully described in the
  235. MSDN, it might be possible that not all required TIB-parts are swapped.
  236. </para>
  237. <note>
  238. <para>
  239. The first call of <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink>
  240. converts the thread into a Windows fiber by invoking <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase
  241. role="special">()</phrase></code>. If desired, <code><phrase role="identifier">ConvertFiberToThread</phrase><phrase
  242. role="special">()</phrase></code> has to be called by the user explicitly
  243. in order to release resources allocated by <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase
  244. role="special">()</phrase></code> (e.g. after using boost.context).
  245. </para>
  246. </note>
  247. </section>
  248. <important>
  249. <para>
  250. Windows using fcontext_t: turn off global program optimization (/GL) and
  251. change /EHsc (compiler assumes that functions declared as extern &quot;C&quot;
  252. never throw a C++ exception) to /EHs (tells compiler assumes that functions
  253. declared as extern &quot;C&quot; may throw an exception).
  254. </para>
  255. </important>
  256. </section>
  257. <section id="fiber.fiber_mgmt">
  258. <title><link linkend="fiber.fiber_mgmt">Fiber management</link></title>
  259. <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h0">
  260. <phrase id="fiber.fiber_mgmt.synopsis"/><link linkend="fiber.fiber_mgmt.synopsis">Synopsis</link>
  261. </bridgehead>
  262. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">all</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  263. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  264. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  265. <phrase role="keyword">class</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">;</phrase>
  266. <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  267. <phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  268. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">SchedAlgo</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  269. <phrase role="keyword">void</phrase> <phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
  270. <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">();</phrase>
  271. <phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
  272. <phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm</phrase><phrase role="special">;</phrase>
  273. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
  274. <phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm_with_properties</phrase><phrase role="special">;</phrase>
  275. <phrase role="keyword">class</phrase> <phrase role="identifier">round_robin</phrase><phrase role="special">;</phrase>
  276. <phrase role="keyword">class</phrase> <phrase role="identifier">shared_round_robin</phrase><phrase role="special">;</phrase>
  277. <phrase role="special">}}</phrase>
  278. <phrase role="keyword">namespace</phrase> <phrase role="identifier">this_fiber</phrase> <phrase role="special">{</phrase>
  279. <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  280. <phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
  281. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  282. <phrase role="keyword">void</phrase> <phrase role="identifier">sleep_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase>
  283. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  284. <phrase role="keyword">void</phrase> <phrase role="identifier">sleep_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">);</phrase>
  285. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
  286. <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
  287. <phrase role="special">}</phrase>
  288. </programlisting>
  289. <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h1">
  290. <phrase id="fiber.fiber_mgmt.tutorial"/><link linkend="fiber.fiber_mgmt.tutorial">Tutorial</link>
  291. </bridgehead>
  292. <para>
  293. Each <link linkend="class_fiber"><code>fiber</code></link> represents a micro-thread which will be launched and managed
  294. cooperatively by a scheduler. Objects of type <link linkend="class_fiber"><code>fiber</code></link> are move-only.
  295. </para>
  296. <programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f1</phrase><phrase role="special">;</phrase> <phrase role="comment">// not-a-fiber</phrase>
  297. <phrase role="keyword">void</phrase> <phrase role="identifier">f</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  298. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f2</phrase><phrase role="special">(</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">);</phrase>
  299. <phrase role="identifier">f1</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">f2</phrase><phrase role="special">);</phrase> <phrase role="comment">// f2 moved to f1</phrase>
  300. <phrase role="special">}</phrase>
  301. </programlisting>
  302. <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h2">
  303. <phrase id="fiber.fiber_mgmt.launching"/><link linkend="fiber.fiber_mgmt.launching">Launching</link>
  304. </bridgehead>
  305. <para>
  306. A new fiber is launched by passing an object of a callable type that can be
  307. invoked with no parameters. If the object must not be copied or moved, then
  308. <emphasis>std::ref</emphasis> can be used to pass in a reference to the function
  309. object. In this case, the user must ensure that the referenced object outlives
  310. the newly-created fiber.
  311. </para>
  312. <programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">callable</phrase> <phrase role="special">{</phrase>
  313. <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()();</phrase>
  314. <phrase role="special">};</phrase>
  315. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">copies_are_safe</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  316. <phrase role="identifier">callable</phrase> <phrase role="identifier">x</phrase><phrase role="special">;</phrase>
  317. <phrase role="keyword">return</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">x</phrase><phrase role="special">);</phrase>
  318. <phrase role="special">}</phrase> <phrase role="comment">// x is destroyed, but the newly-created fiber has a copy, so this is OK</phrase>
  319. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">oops</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  320. <phrase role="identifier">callable</phrase> <phrase role="identifier">x</phrase><phrase role="special">;</phrase>
  321. <phrase role="keyword">return</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">x</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  322. <phrase role="special">}</phrase> <phrase role="comment">// x is destroyed, but the newly-created fiber still has a reference</phrase>
  323. <phrase role="comment">// this leads to undefined behaviour</phrase>
  324. </programlisting>
  325. <para>
  326. The spawned <link linkend="class_fiber"><code>fiber</code></link> does not immediately start running. It is enqueued
  327. in the list of ready-to-run fibers, and will run when the scheduler gets around
  328. to it.
  329. </para>
  330. <anchor id="exceptions"/>
  331. <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h3">
  332. <phrase id="fiber.fiber_mgmt.exceptions"/><link linkend="fiber.fiber_mgmt.exceptions">Exceptions</link>
  333. </bridgehead>
  334. <para>
  335. An exception escaping from the function or callable object passed to the <link linkend="class_fiber"><code>fiber</code></link>
  336. constructor
  337. calls <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  338. role="identifier">terminate</phrase><phrase role="special">()</phrase></code>.
  339. If you need to know which exception was thrown, use <link linkend="class_future"><code>future&lt;&gt;</code></link> or
  340. <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link>.
  341. </para>
  342. <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h4">
  343. <phrase id="fiber.fiber_mgmt.detaching"/><link linkend="fiber.fiber_mgmt.detaching">Detaching</link>
  344. </bridgehead>
  345. <para>
  346. A <link linkend="class_fiber"><code>fiber</code></link> can be detached by explicitly invoking the <link linkend="fiber_detach"><code>fiber::detach()</code></link> member
  347. function. After <link linkend="fiber_detach"><code>fiber::detach()</code></link> is called on a fiber object, that
  348. object represents <emphasis>not-a-fiber</emphasis>. The fiber object may then
  349. safely be destroyed.
  350. </para>
  351. <programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
  352. </programlisting>
  353. <para>
  354. <emphasis role="bold">Boost.Fiber</emphasis> provides a number of ways to wait
  355. for a running fiber to complete. You can coordinate even with a detached fiber
  356. using a <link linkend="class_mutex"><code>mutex</code></link>, or <link linkend="class_condition_variable"><code>condition_variable</code></link>, or
  357. any of the other <link linkend="synchronization">synchronization objects</link>
  358. provided by the library.
  359. </para>
  360. <para>
  361. If a detached fiber is still running when the thread&#8217;s main fiber terminates,
  362. the thread will not shut down.
  363. </para>
  364. <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h5">
  365. <phrase id="fiber.fiber_mgmt.joining"/><link linkend="fiber.fiber_mgmt.joining">Joining</link>
  366. </bridgehead>
  367. <para>
  368. In order to wait for a fiber to finish, the <link linkend="fiber_join"><code>fiber::join()</code></link> member function
  369. of the <link linkend="class_fiber"><code>fiber</code></link> object can be used. <link linkend="fiber_join"><code>fiber::join()</code></link> will block
  370. until the <link linkend="class_fiber"><code>fiber</code></link> object has completed.
  371. </para>
  372. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  373. <phrase role="special">...</phrase>
  374. <phrase role="special">}</phrase>
  375. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">(</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">);</phrase>
  376. <phrase role="special">...</phrase>
  377. <phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  378. </programlisting>
  379. <para>
  380. If the fiber has already completed, then <link linkend="fiber_join"><code>fiber::join()</code></link> returns immediately
  381. and the joined <link linkend="class_fiber"><code>fiber</code></link> object becomes <emphasis>not-a-fiber</emphasis>.
  382. </para>
  383. <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h6">
  384. <phrase id="fiber.fiber_mgmt.destruction"/><link linkend="fiber.fiber_mgmt.destruction">Destruction</link>
  385. </bridgehead>
  386. <para>
  387. When a <link linkend="class_fiber"><code>fiber</code></link> object representing a valid execution context (the fiber
  388. is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>) is destroyed, the program terminates. If
  389. you intend the fiber to outlive the <link linkend="class_fiber"><code>fiber</code></link> object that launched it,
  390. use the <link linkend="fiber_detach"><code>fiber::detach()</code></link> method.
  391. </para>
  392. <programlisting><phrase role="special">{</phrase>
  393. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">(</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">);</phrase>
  394. <phrase role="special">}</phrase> <phrase role="comment">// std::terminate() will be called</phrase>
  395. <phrase role="special">{</phrase>
  396. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">(</phrase><phrase role="identifier">some_fn</phrase><phrase role="special">);</phrase>
  397. <phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
  398. <phrase role="special">}</phrase> <phrase role="comment">// okay, program continues</phrase>
  399. </programlisting>
  400. <anchor id="class_fiber_id"/>
  401. <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h7">
  402. <phrase id="fiber.fiber_mgmt.fiber_ids"/><link linkend="fiber.fiber_mgmt.fiber_ids">Fiber
  403. IDs</link>
  404. </bridgehead>
  405. <para>
  406. Objects of class <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
  407. role="special">::</phrase><phrase role="identifier">id</phrase></code></link> can be
  408. used to identify fibers. Each running <link linkend="class_fiber"><code>fiber</code></link> has a unique <link linkend="class_fiber_id"><code><phrase
  409. role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase></code></link> obtainable
  410. from the corresponding <link linkend="class_fiber"><code>fiber</code></link>
  411. by calling the <link linkend="fiber_get_id"><code>fiber::get_id()</code></link> member
  412. function. Objects of class <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
  413. role="special">::</phrase><phrase role="identifier">id</phrase></code></link> can be
  414. copied, and used as keys in associative containers: the full range of comparison
  415. operators is provided. They can also be written to an output stream using the
  416. stream insertion operator, though the output format is unspecified.
  417. </para>
  418. <para>
  419. Each instance of <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
  420. role="special">::</phrase><phrase role="identifier">id</phrase></code></link> either
  421. refers to some fiber, or <emphasis>not-a-fiber</emphasis>. Instances that refer
  422. to <emphasis>not-a-fiber</emphasis> compare equal to each other, but not equal
  423. to any instances that refer to an actual fiber. The comparison operators on
  424. <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
  425. role="identifier">id</phrase></code></link> yield a total order for every non-equal
  426. <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
  427. role="identifier">id</phrase></code></link>.
  428. </para>
  429. <anchor id="class_launch"/>
  430. <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h8">
  431. <phrase id="fiber.fiber_mgmt.enumeration__code__phrase_role__identifier__launch__phrase___code_"/><link
  432. linkend="fiber.fiber_mgmt.enumeration__code__phrase_role__identifier__launch__phrase___code_">Enumeration
  433. <code><phrase role="identifier">launch</phrase></code></link>
  434. </bridgehead>
  435. <para>
  436. <code><phrase role="identifier">launch</phrase></code> specifies whether control
  437. passes immediately into a newly-launched fiber.
  438. </para>
  439. <programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">launch</phrase> <phrase role="special">{</phrase>
  440. <phrase role="identifier">dispatch</phrase><phrase role="special">,</phrase>
  441. <phrase role="identifier">post</phrase>
  442. <phrase role="special">};</phrase>
  443. </programlisting>
  444. <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h9">
  445. <phrase id="fiber.fiber_mgmt._code__phrase_role__identifier__dispatch__phrase___code_"/><link
  446. linkend="fiber.fiber_mgmt._code__phrase_role__identifier__dispatch__phrase___code_"><code><phrase
  447. role="identifier">dispatch</phrase></code></link>
  448. </bridgehead>
  449. <variablelist>
  450. <title></title>
  451. <varlistentry>
  452. <term>Effects:</term>
  453. <listitem>
  454. <para>
  455. A fiber launched with <code><phrase role="identifier">launch</phrase>
  456. <phrase role="special">==</phrase> <phrase role="identifier">dispatch</phrase></code>
  457. is entered immediately. In other words, launching a fiber with <code><phrase
  458. role="identifier">dispatch</phrase></code> suspends the caller (the previously-running
  459. fiber) until the fiber scheduler has a chance to resume it later.
  460. </para>
  461. </listitem>
  462. </varlistentry>
  463. </variablelist>
  464. <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h10">
  465. <phrase id="fiber.fiber_mgmt._code__phrase_role__identifier__post__phrase___code_"/><link
  466. linkend="fiber.fiber_mgmt._code__phrase_role__identifier__post__phrase___code_"><code><phrase
  467. role="identifier">post</phrase></code></link>
  468. </bridgehead>
  469. <variablelist>
  470. <title></title>
  471. <varlistentry>
  472. <term>Effects:</term>
  473. <listitem>
  474. <para>
  475. A fiber launched with <code><phrase role="identifier">launch</phrase>
  476. <phrase role="special">==</phrase> <phrase role="identifier">post</phrase></code>
  477. is passed to the fiber scheduler as ready, but it is not yet entered.
  478. The caller (the previously-running fiber) continues executing. The newly-launched
  479. fiber will be entered when the fiber scheduler has a chance to resume
  480. it later.
  481. </para>
  482. </listitem>
  483. </varlistentry>
  484. <varlistentry>
  485. <term>Note:</term>
  486. <listitem>
  487. <para>
  488. If <code><phrase role="identifier">launch</phrase></code> is not explicitly
  489. specified, <code><phrase role="identifier">post</phrase></code> is the
  490. default.
  491. </para>
  492. </listitem>
  493. </varlistentry>
  494. </variablelist>
  495. <section id="fiber.fiber_mgmt.fiber">
  496. <title><anchor id="class_fiber"/><link linkend="fiber.fiber_mgmt.fiber">Class
  497. <code><phrase role="identifier">fiber</phrase></code></link></title>
  498. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  499. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  500. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  501. <phrase role="keyword">class</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">{</phrase>
  502. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  503. <phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
  504. <phrase role="keyword">constexpr</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  505. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  506. <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...);</phrase>
  507. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  508. <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...);</phrase>
  509. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  510. <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">&amp;&amp;,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...);</phrase>
  511. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  512. <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link><phrase role="special">,</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">&amp;&amp;,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...);</phrase>
  513. <phrase role="special">~</phrase><phrase role="identifier">fiber</phrase><phrase role="special">();</phrase>
  514. <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  515. <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  516. <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  517. <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  518. <phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  519. <phrase role="keyword">bool</phrase> <phrase role="identifier">joinable</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  520. <phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  521. <phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
  522. <phrase role="keyword">void</phrase> <phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  523. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
  524. <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
  525. <phrase role="special">};</phrase>
  526. <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  527. <phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  528. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">SchedAlgo</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  529. <phrase role="keyword">void</phrase> <phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  530. <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  531. <phrase role="special">}}</phrase>
  532. </programlisting>
  533. <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h0">
  534. <phrase id="fiber.fiber_mgmt.fiber.default_constructor"/><link linkend="fiber.fiber_mgmt.fiber.default_constructor">Default
  535. constructor</link>
  536. </bridgehead>
  537. <programlisting><phrase role="keyword">constexpr</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  538. </programlisting>
  539. <variablelist>
  540. <title></title>
  541. <varlistentry>
  542. <term>Effects:</term>
  543. <listitem>
  544. <para>
  545. Constructs a <link linkend="class_fiber"><code>fiber</code></link> instance that refers to <emphasis>not-a-fiber</emphasis>.
  546. </para>
  547. </listitem>
  548. </varlistentry>
  549. <varlistentry>
  550. <term>Postconditions:</term>
  551. <listitem>
  552. <para>
  553. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  554. role="identifier">get_id</phrase><phrase role="special">()</phrase>
  555. <phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase
  556. role="special">::</phrase><phrase role="identifier">id</phrase><phrase
  557. role="special">()</phrase></code>
  558. </para>
  559. </listitem>
  560. </varlistentry>
  561. <varlistentry>
  562. <term>Throws:</term>
  563. <listitem>
  564. <para>
  565. Nothing
  566. </para>
  567. </listitem>
  568. </varlistentry>
  569. </variablelist>
  570. <anchor id="fiber_fiber"/>
  571. <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h1">
  572. <phrase id="fiber.fiber_mgmt.fiber.constructor"/><link linkend="fiber.fiber_mgmt.fiber.constructor">Constructor</link>
  573. </bridgehead>
  574. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  575. <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
  576. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  577. <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
  578. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  579. <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
  580. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  581. <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase>
  582. <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
  583. </programlisting>
  584. <variablelist>
  585. <title></title>
  586. <varlistentry>
  587. <term>Preconditions:</term>
  588. <listitem>
  589. <para>
  590. <code><phrase role="identifier">Fn</phrase></code> must be copyable
  591. or movable.
  592. </para>
  593. </listitem>
  594. </varlistentry>
  595. <varlistentry>
  596. <term>Effects:</term>
  597. <listitem>
  598. <para>
  599. <code><phrase role="identifier">fn</phrase></code> is copied or moved
  600. into internal storage for access by the new fiber. If <link linkend="class_launch"><code>launch</code></link> is
  601. specified (or defaulted) to <code><phrase role="identifier">post</phrase></code>,
  602. the new fiber is marked <quote>ready</quote> and will be entered at
  603. the next opportunity. If <code><phrase role="identifier">launch</phrase></code>
  604. is specified as <code><phrase role="identifier">dispatch</phrase></code>,
  605. the calling fiber is suspended and the new fiber is entered immediately.
  606. </para>
  607. </listitem>
  608. </varlistentry>
  609. <varlistentry>
  610. <term>Postconditions:</term>
  611. <listitem>
  612. <para>
  613. <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  614. refers to the newly created fiber of execution.
  615. </para>
  616. </listitem>
  617. </varlistentry>
  618. <varlistentry>
  619. <term>Throws:</term>
  620. <listitem>
  621. <para>
  622. <code><phrase role="identifier">fiber_error</phrase></code> if an error
  623. occurs.
  624. </para>
  625. </listitem>
  626. </varlistentry>
  627. <varlistentry>
  628. <term>Note:</term>
  629. <listitem>
  630. <para>
  631. <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link>
  632. is required to allocate a stack for the internal __econtext__. If
  633. <code><phrase role="identifier">StackAllocator</phrase></code> is not
  634. explicitly passed, the default stack allocator depends on <code><phrase
  635. role="identifier">BOOST_USE_SEGMENTED_STACKS</phrase></code>: if defined,
  636. you will get a <link linkend="class_segmented_stack"><code>segmented_stack</code></link>, else a <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link>.
  637. </para>
  638. </listitem>
  639. </varlistentry>
  640. <varlistentry>
  641. <term>See also:</term>
  642. <listitem>
  643. <para>
  644. <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
  645. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  646. role="identifier">allocator_arg_t</phrase></code></ulink>, <link linkend="stack">Stack
  647. allocation</link>
  648. </para>
  649. </listitem>
  650. </varlistentry>
  651. </variablelist>
  652. <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h2">
  653. <phrase id="fiber.fiber_mgmt.fiber.move_constructor"/><link linkend="fiber.fiber_mgmt.fiber.move_constructor">Move
  654. constructor</link>
  655. </bridgehead>
  656. <programlisting><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  657. </programlisting>
  658. <variablelist>
  659. <title></title>
  660. <varlistentry>
  661. <term>Effects:</term>
  662. <listitem>
  663. <para>
  664. Transfers ownership of the fiber managed by <code><phrase role="identifier">other</phrase></code>
  665. to the newly constructed <link linkend="class_fiber"><code>fiber</code></link> instance.
  666. </para>
  667. </listitem>
  668. </varlistentry>
  669. <varlistentry>
  670. <term>Postconditions:</term>
  671. <listitem>
  672. <para>
  673. <code><phrase role="identifier">other</phrase><phrase role="special">.</phrase><phrase
  674. role="identifier">get_id</phrase><phrase role="special">()</phrase>
  675. <phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase
  676. role="special">::</phrase><phrase role="identifier">id</phrase><phrase
  677. role="special">()</phrase></code> and <code><phrase role="identifier">get_id</phrase><phrase
  678. role="special">()</phrase></code> returns the value of <code><phrase
  679. role="identifier">other</phrase><phrase role="special">.</phrase><phrase
  680. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  681. prior to the construction
  682. </para>
  683. </listitem>
  684. </varlistentry>
  685. <varlistentry>
  686. <term>Throws:</term>
  687. <listitem>
  688. <para>
  689. Nothing
  690. </para>
  691. </listitem>
  692. </varlistentry>
  693. </variablelist>
  694. <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h3">
  695. <phrase id="fiber.fiber_mgmt.fiber.move_assignment_operator"/><link linkend="fiber.fiber_mgmt.fiber.move_assignment_operator">Move
  696. assignment operator</link>
  697. </bridgehead>
  698. <programlisting><phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  699. </programlisting>
  700. <variablelist>
  701. <title></title>
  702. <varlistentry>
  703. <term>Effects:</term>
  704. <listitem>
  705. <para>
  706. Transfers ownership of the fiber managed by <code><phrase role="identifier">other</phrase></code>
  707. (if any) to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
  708. </para>
  709. </listitem>
  710. </varlistentry>
  711. <varlistentry>
  712. <term>Postconditions:</term>
  713. <listitem>
  714. <para>
  715. <code><phrase role="identifier">other</phrase><phrase role="special">-&gt;</phrase><phrase
  716. role="identifier">get_id</phrase><phrase role="special">()</phrase>
  717. <phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase
  718. role="special">::</phrase><phrase role="identifier">id</phrase><phrase
  719. role="special">()</phrase></code> and <code><phrase role="identifier">get_id</phrase><phrase
  720. role="special">()</phrase></code> returns the value of <code><phrase
  721. role="identifier">other</phrase><phrase role="special">.</phrase><phrase
  722. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  723. prior to the assignment.
  724. </para>
  725. </listitem>
  726. </varlistentry>
  727. <varlistentry>
  728. <term>Throws:</term>
  729. <listitem>
  730. <para>
  731. Nothing
  732. </para>
  733. </listitem>
  734. </varlistentry>
  735. </variablelist>
  736. <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h4">
  737. <phrase id="fiber.fiber_mgmt.fiber.destructor"/><link linkend="fiber.fiber_mgmt.fiber.destructor">Destructor</link>
  738. </bridgehead>
  739. <programlisting><phrase role="special">~</phrase><phrase role="identifier">fiber</phrase><phrase role="special">();</phrase>
  740. </programlisting>
  741. <variablelist>
  742. <title></title>
  743. <varlistentry>
  744. <term>Effects:</term>
  745. <listitem>
  746. <para>
  747. If the fiber is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>, calls std::terminate.
  748. Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
  749. </para>
  750. </listitem>
  751. </varlistentry>
  752. <varlistentry>
  753. <term>Note:</term>
  754. <listitem>
  755. <para>
  756. The programmer must ensure that the destructor is never executed while
  757. the fiber is still <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>. Even if you know
  758. that the fiber has completed, you must still call either <link linkend="fiber_join"><code>fiber::join()</code></link> or
  759. <link linkend="fiber_detach"><code>fiber::detach()</code></link> before destroying the <code><phrase role="identifier">fiber</phrase></code>
  760. object.
  761. </para>
  762. </listitem>
  763. </varlistentry>
  764. </variablelist>
  765. <para>
  766. <bridgehead renderas="sect4" id="fiber_joinable_bridgehead">
  767. <phrase id="fiber_joinable"/>
  768. <link linkend="fiber_joinable">Member function <code>joinable</code>()</link>
  769. </bridgehead>
  770. </para>
  771. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">joinable</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  772. </programlisting>
  773. <variablelist>
  774. <title></title>
  775. <varlistentry>
  776. <term>Returns:</term>
  777. <listitem>
  778. <para>
  779. <code><phrase role="keyword">true</phrase></code> if <code><phrase
  780. role="special">*</phrase><phrase role="keyword">this</phrase></code>
  781. refers to a fiber of execution, which may or may not have completed;
  782. otherwise <code><phrase role="keyword">false</phrase></code>.
  783. </para>
  784. </listitem>
  785. </varlistentry>
  786. <varlistentry>
  787. <term>Throws:</term>
  788. <listitem>
  789. <para>
  790. Nothing
  791. </para>
  792. </listitem>
  793. </varlistentry>
  794. </variablelist>
  795. <para>
  796. <bridgehead renderas="sect4" id="fiber_join_bridgehead">
  797. <phrase id="fiber_join"/>
  798. <link linkend="fiber_join">Member function <code>join</code>()</link>
  799. </bridgehead>
  800. </para>
  801. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  802. </programlisting>
  803. <variablelist>
  804. <title></title>
  805. <varlistentry>
  806. <term>Preconditions:</term>
  807. <listitem>
  808. <para>
  809. the fiber is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>.
  810. </para>
  811. </listitem>
  812. </varlistentry>
  813. <varlistentry>
  814. <term>Effects:</term>
  815. <listitem>
  816. <para>
  817. Waits for the referenced fiber of execution to complete.
  818. </para>
  819. </listitem>
  820. </varlistentry>
  821. <varlistentry>
  822. <term>Postconditions:</term>
  823. <listitem>
  824. <para>
  825. The fiber of execution referenced on entry has completed. <code><phrase
  826. role="special">*</phrase><phrase role="keyword">this</phrase></code>
  827. no longer refers to any fiber of execution.
  828. </para>
  829. </listitem>
  830. </varlistentry>
  831. <varlistentry>
  832. <term>Throws:</term>
  833. <listitem>
  834. <para>
  835. <code><phrase role="identifier">fiber_error</phrase></code>
  836. </para>
  837. </listitem>
  838. </varlistentry>
  839. <varlistentry>
  840. <term>Error Conditions:</term>
  841. <listitem>
  842. <para>
  843. <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
  844. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  845. role="identifier">get_id</phrase><phrase role="special">()</phrase>
  846. <phrase role="special">==</phrase> <phrase role="identifier">boost</phrase><phrase
  847. role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase
  848. role="special">::</phrase><phrase role="identifier">get_id</phrase><phrase
  849. role="special">()</phrase></code>. <emphasis role="bold">invalid_argument</emphasis>:
  850. if the fiber is not <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>.
  851. </para>
  852. </listitem>
  853. </varlistentry>
  854. </variablelist>
  855. <para>
  856. <bridgehead renderas="sect4" id="fiber_detach_bridgehead">
  857. <phrase id="fiber_detach"/>
  858. <link linkend="fiber_detach">Member function <code>detach</code>()</link>
  859. </bridgehead>
  860. </para>
  861. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
  862. </programlisting>
  863. <variablelist>
  864. <title></title>
  865. <varlistentry>
  866. <term>Preconditions:</term>
  867. <listitem>
  868. <para>
  869. the fiber is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>.
  870. </para>
  871. </listitem>
  872. </varlistentry>
  873. <varlistentry>
  874. <term>Effects:</term>
  875. <listitem>
  876. <para>
  877. The fiber of execution becomes detached, and no longer has an associated
  878. <link linkend="class_fiber"><code>fiber</code></link> object.
  879. </para>
  880. </listitem>
  881. </varlistentry>
  882. <varlistentry>
  883. <term>Postconditions:</term>
  884. <listitem>
  885. <para>
  886. <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  887. no longer refers to any fiber of execution.
  888. </para>
  889. </listitem>
  890. </varlistentry>
  891. <varlistentry>
  892. <term>Throws:</term>
  893. <listitem>
  894. <para>
  895. <code><phrase role="identifier">fiber_error</phrase></code>
  896. </para>
  897. </listitem>
  898. </varlistentry>
  899. <varlistentry>
  900. <term>Error Conditions:</term>
  901. <listitem>
  902. <para>
  903. <emphasis role="bold">invalid_argument</emphasis>: if the fiber is
  904. not <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>.
  905. </para>
  906. </listitem>
  907. </varlistentry>
  908. </variablelist>
  909. <para>
  910. <bridgehead renderas="sect4" id="fiber_get_id_bridgehead">
  911. <phrase id="fiber_get_id"/>
  912. <link linkend="fiber_get_id">Member function <code>get_id</code>()</link>
  913. </bridgehead>
  914. </para>
  915. <programlisting><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  916. </programlisting>
  917. <variablelist>
  918. <title></title>
  919. <varlistentry>
  920. <term>Returns:</term>
  921. <listitem>
  922. <para>
  923. If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  924. refers to a fiber of execution, an instance of <link linkend="class_fiber_id"><code><phrase
  925. role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
  926. role="identifier">id</phrase></code></link> that represents that fiber. Otherwise
  927. returns a default-constructed <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
  928. role="special">::</phrase><phrase role="identifier">id</phrase></code></link>.
  929. </para>
  930. </listitem>
  931. </varlistentry>
  932. <varlistentry>
  933. <term>Throws:</term>
  934. <listitem>
  935. <para>
  936. Nothing
  937. </para>
  938. </listitem>
  939. </varlistentry>
  940. <varlistentry>
  941. <term>See also:</term>
  942. <listitem>
  943. <para>
  944. <link linkend="this_fiber_get_id"><code>this_fiber::get_id()</code></link>
  945. </para>
  946. </listitem>
  947. </varlistentry>
  948. </variablelist>
  949. <para>
  950. <bridgehead renderas="sect4" id="fiber_properties_bridgehead">
  951. <phrase id="fiber_properties"/>
  952. <link linkend="fiber_properties">Templated member
  953. function <code>properties</code>()</link>
  954. </bridgehead>
  955. </para>
  956. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
  957. <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
  958. </programlisting>
  959. <variablelist>
  960. <title></title>
  961. <varlistentry>
  962. <term>Preconditions:</term>
  963. <listitem>
  964. <para>
  965. <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  966. refers to a fiber of execution. <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link> has
  967. been called from this thread with a subclass of <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> with
  968. the same template argument <code><phrase role="identifier">PROPS</phrase></code>.
  969. </para>
  970. </listitem>
  971. </varlistentry>
  972. <varlistentry>
  973. <term>Returns:</term>
  974. <listitem>
  975. <para>
  976. a reference to the scheduler properties instance for <code><phrase
  977. role="special">*</phrase><phrase role="keyword">this</phrase></code>.
  978. </para>
  979. </listitem>
  980. </varlistentry>
  981. <varlistentry>
  982. <term>Throws:</term>
  983. <listitem>
  984. <para>
  985. <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  986. role="identifier">bad_cast</phrase></code> if <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
  987. role="special">()</phrase></code> was called with a <code><phrase role="identifier">algorithm_with_properties</phrase></code>
  988. subclass with some other template parameter than <code><phrase role="identifier">PROPS</phrase></code>.
  989. </para>
  990. </listitem>
  991. </varlistentry>
  992. <varlistentry>
  993. <term>Note:</term>
  994. <listitem>
  995. <para>
  996. <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> provides
  997. a way for a user-coded scheduler to associate extended properties,
  998. such as priority, with a fiber instance. This method allows access
  999. to those user-provided properties.
  1000. </para>
  1001. </listitem>
  1002. </varlistentry>
  1003. <varlistentry>
  1004. <term>See also:</term>
  1005. <listitem>
  1006. <para>
  1007. <link linkend="custom">Customization</link>
  1008. </para>
  1009. </listitem>
  1010. </varlistentry>
  1011. </variablelist>
  1012. <para>
  1013. <bridgehead renderas="sect4" id="fiber_swap_bridgehead">
  1014. <phrase id="fiber_swap"/>
  1015. <link linkend="fiber_swap">Member function <code>swap</code>()</link>
  1016. </bridgehead>
  1017. </para>
  1018. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1019. </programlisting>
  1020. <variablelist>
  1021. <title></title>
  1022. <varlistentry>
  1023. <term>Effects:</term>
  1024. <listitem>
  1025. <para>
  1026. Exchanges the fiber of execution associated with <code><phrase role="special">*</phrase><phrase
  1027. role="keyword">this</phrase></code> and <code><phrase role="identifier">other</phrase></code>,
  1028. so <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  1029. becomes associated with the fiber formerly associated with <code><phrase
  1030. role="identifier">other</phrase></code>, and vice-versa.
  1031. </para>
  1032. </listitem>
  1033. </varlistentry>
  1034. <varlistentry>
  1035. <term>Postconditions:</term>
  1036. <listitem>
  1037. <para>
  1038. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  1039. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  1040. returns the same value as <code><phrase role="identifier">other</phrase><phrase
  1041. role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase
  1042. role="special">()</phrase></code> prior to the call. <code><phrase
  1043. role="identifier">other</phrase><phrase role="special">.</phrase><phrase
  1044. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  1045. returns the same value as <code><phrase role="keyword">this</phrase><phrase
  1046. role="special">-&gt;</phrase><phrase role="identifier">get_id</phrase><phrase
  1047. role="special">()</phrase></code> prior to the call.
  1048. </para>
  1049. </listitem>
  1050. </varlistentry>
  1051. <varlistentry>
  1052. <term>Throws:</term>
  1053. <listitem>
  1054. <para>
  1055. Nothing
  1056. </para>
  1057. </listitem>
  1058. </varlistentry>
  1059. </variablelist>
  1060. <para>
  1061. <bridgehead renderas="sect4" id="swap_for_fiber_bridgehead">
  1062. <phrase id="swap_for_fiber"/>
  1063. <link linkend="swap_for_fiber">Non-member function
  1064. <code>swap()</code></link>
  1065. </bridgehead>
  1066. </para>
  1067. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1068. </programlisting>
  1069. <variablelist>
  1070. <title></title>
  1071. <varlistentry>
  1072. <term>Effects:</term>
  1073. <listitem>
  1074. <para>
  1075. Same as <code><phrase role="identifier">l</phrase><phrase role="special">.</phrase><phrase
  1076. role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase
  1077. role="identifier">r</phrase><phrase role="special">)</phrase></code>.
  1078. </para>
  1079. </listitem>
  1080. </varlistentry>
  1081. <varlistentry>
  1082. <term>Throws:</term>
  1083. <listitem>
  1084. <para>
  1085. Nothing
  1086. </para>
  1087. </listitem>
  1088. </varlistentry>
  1089. </variablelist>
  1090. <para>
  1091. <bridgehead renderas="sect4" id="operator&lt;_bridgehead">
  1092. <phrase id="operator&lt;"/>
  1093. <link linkend="operator&lt;">Non-member function <code>operator&lt;()</code></link>
  1094. </bridgehead>
  1095. </para>
  1096. <programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1097. </programlisting>
  1098. <variablelist>
  1099. <title></title>
  1100. <varlistentry>
  1101. <term>Returns:</term>
  1102. <listitem>
  1103. <para>
  1104. <code><phrase role="keyword">true</phrase></code> if <code><phrase
  1105. role="identifier">l</phrase><phrase role="special">.</phrase><phrase
  1106. role="identifier">get_id</phrase><phrase role="special">()</phrase>
  1107. <phrase role="special">&lt;</phrase> <phrase role="identifier">r</phrase><phrase
  1108. role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase
  1109. role="special">()</phrase></code> is <code><phrase role="keyword">true</phrase></code>,
  1110. false otherwise.
  1111. </para>
  1112. </listitem>
  1113. </varlistentry>
  1114. <varlistentry>
  1115. <term>Throws:</term>
  1116. <listitem>
  1117. <para>
  1118. Nothing.
  1119. </para>
  1120. </listitem>
  1121. </varlistentry>
  1122. </variablelist>
  1123. <para>
  1124. <bridgehead renderas="sect4" id="use_scheduling_algorithm_bridgehead">
  1125. <phrase id="use_scheduling_algorithm"/>
  1126. <link linkend="use_scheduling_algorithm">Non-member
  1127. function <code>use_scheduling_algorithm()</code></link>
  1128. </bridgehead>
  1129. </para>
  1130. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">SchedAlgo</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  1131. <phrase role="keyword">void</phrase> <phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1132. </programlisting>
  1133. <variablelist>
  1134. <title></title>
  1135. <varlistentry>
  1136. <term>Effects:</term>
  1137. <listitem>
  1138. <para>
  1139. Directs <emphasis role="bold">Boost.Fiber</emphasis> to use <code><phrase
  1140. role="identifier">SchedAlgo</phrase></code>, which must be a concrete
  1141. subclass of <link linkend="class_algorithm"><code>algorithm</code></link>, as the scheduling algorithm for
  1142. all fibers in the current thread. Pass any required <code><phrase role="identifier">SchedAlgo</phrase></code>
  1143. constructor arguments as <code><phrase role="identifier">args</phrase></code>.
  1144. </para>
  1145. </listitem>
  1146. </varlistentry>
  1147. <varlistentry>
  1148. <term>Note:</term>
  1149. <listitem>
  1150. <para>
  1151. If you want a given thread to use a non-default scheduling algorithm,
  1152. make that thread call <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
  1153. role="special">()</phrase></code> before any other <emphasis role="bold">Boost.Fiber</emphasis>
  1154. entry point. If no scheduler has been set for the current thread by
  1155. the time <emphasis role="bold">Boost.Fiber</emphasis> needs to use
  1156. it, the library will create a default <link linkend="class_round_robin"><code>round_robin</code></link> instance
  1157. for this thread.
  1158. </para>
  1159. </listitem>
  1160. </varlistentry>
  1161. <varlistentry>
  1162. <term>Throws:</term>
  1163. <listitem>
  1164. <para>
  1165. Nothing
  1166. </para>
  1167. </listitem>
  1168. </varlistentry>
  1169. <varlistentry>
  1170. <term>See also:</term>
  1171. <listitem>
  1172. <para>
  1173. <link linkend="scheduling">Scheduling</link>, <link linkend="custom">Customization</link>
  1174. </para>
  1175. </listitem>
  1176. </varlistentry>
  1177. </variablelist>
  1178. <para>
  1179. <bridgehead renderas="sect4" id="has_ready_fibers_bridgehead">
  1180. <phrase id="has_ready_fibers"/>
  1181. <link linkend="has_ready_fibers">Non-member function
  1182. <code>has_ready_fibers()</code></link>
  1183. </bridgehead>
  1184. </para>
  1185. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1186. </programlisting>
  1187. <variablelist>
  1188. <title></title>
  1189. <varlistentry>
  1190. <term>Returns:</term>
  1191. <listitem>
  1192. <para>
  1193. <code><phrase role="keyword">true</phrase></code> if scheduler has
  1194. fibers ready to run.
  1195. </para>
  1196. </listitem>
  1197. </varlistentry>
  1198. <varlistentry>
  1199. <term>Throws:</term>
  1200. <listitem>
  1201. <para>
  1202. Nothing
  1203. </para>
  1204. </listitem>
  1205. </varlistentry>
  1206. <varlistentry>
  1207. <term>Note:</term>
  1208. <listitem>
  1209. <para>
  1210. Can be used for work-stealing to find an idle scheduler.
  1211. </para>
  1212. </listitem>
  1213. </varlistentry>
  1214. </variablelist>
  1215. </section>
  1216. <section id="fiber.fiber_mgmt.id">
  1217. <title><anchor id="class_id"/><link linkend="fiber.fiber_mgmt.id">Class fiber::id</link></title>
  1218. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  1219. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  1220. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  1221. <phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase> <phrase role="special">{</phrase>
  1222. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  1223. <phrase role="keyword">constexpr</phrase> <phrase role="identifier">id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1224. <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">==(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1225. <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1226. <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1227. <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&gt;(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1228. <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1229. <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&gt;=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1230. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">&gt;</phrase>
  1231. <phrase role="keyword">friend</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase>
  1232. <phrase role="keyword">operator</phrase><phrase role="special">&lt;&lt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;,</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;);</phrase>
  1233. <phrase role="special">};</phrase>
  1234. <phrase role="special">}}</phrase>
  1235. </programlisting>
  1236. <bridgehead renderas="sect4" id="fiber.fiber_mgmt.id.h0">
  1237. <phrase id="fiber.fiber_mgmt.id.constructor"/><link linkend="fiber.fiber_mgmt.id.constructor">Constructor</link>
  1238. </bridgehead>
  1239. <programlisting><phrase role="keyword">constexpr</phrase> <phrase role="identifier">id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1240. </programlisting>
  1241. <variablelist>
  1242. <title></title>
  1243. <varlistentry>
  1244. <term>Effects:</term>
  1245. <listitem>
  1246. <para>
  1247. Represents an instance of <emphasis>not-a-fiber</emphasis>.
  1248. </para>
  1249. </listitem>
  1250. </varlistentry>
  1251. <varlistentry>
  1252. <term>Throws:</term>
  1253. <listitem>
  1254. <para>
  1255. Nothing.
  1256. </para>
  1257. </listitem>
  1258. </varlistentry>
  1259. </variablelist>
  1260. <para>
  1261. <bridgehead renderas="sect4" id="id_operator_equal_bridgehead">
  1262. <phrase id="id_operator_equal"/>
  1263. <link linkend="id_operator_equal">Member function
  1264. <code>operator==</code>()</link>
  1265. </bridgehead>
  1266. </para>
  1267. <programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">==(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1268. </programlisting>
  1269. <variablelist>
  1270. <title></title>
  1271. <varlistentry>
  1272. <term>Returns:</term>
  1273. <listitem>
  1274. <para>
  1275. <code><phrase role="keyword">true</phrase></code> if <code><phrase
  1276. role="special">*</phrase><phrase role="keyword">this</phrase></code>
  1277. and <code><phrase role="identifier">other</phrase></code> represent
  1278. the same fiber, or both represent <emphasis>not-a-fiber</emphasis>,
  1279. <code><phrase role="keyword">false</phrase></code> otherwise.
  1280. </para>
  1281. </listitem>
  1282. </varlistentry>
  1283. <varlistentry>
  1284. <term>Throws:</term>
  1285. <listitem>
  1286. <para>
  1287. Nothing.
  1288. </para>
  1289. </listitem>
  1290. </varlistentry>
  1291. </variablelist>
  1292. <para>
  1293. <bridgehead renderas="sect4" id="id_operator_not_equal_bridgehead">
  1294. <phrase id="id_operator_not_equal"/>
  1295. <link linkend="id_operator_not_equal">Member
  1296. function <code>operator!=</code>()</link>
  1297. </bridgehead>
  1298. </para>
  1299. <programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1300. </programlisting>
  1301. <variablelist>
  1302. <title></title>
  1303. <varlistentry>
  1304. <term>Returns:</term>
  1305. <listitem>
  1306. <para>
  1307. <code>! (other == * this)</code>
  1308. </para>
  1309. </listitem>
  1310. </varlistentry>
  1311. <varlistentry>
  1312. <term>Throws:</term>
  1313. <listitem>
  1314. <para>
  1315. Nothing.
  1316. </para>
  1317. </listitem>
  1318. </varlistentry>
  1319. </variablelist>
  1320. <para>
  1321. <bridgehead renderas="sect4" id="id_operator_less_bridgehead">
  1322. <phrase id="id_operator_less"/>
  1323. <link linkend="id_operator_less">Member function
  1324. <code>operator&lt;</code>()</link>
  1325. </bridgehead>
  1326. </para>
  1327. <programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1328. </programlisting>
  1329. <variablelist>
  1330. <title></title>
  1331. <varlistentry>
  1332. <term>Returns:</term>
  1333. <listitem>
  1334. <para>
  1335. <code><phrase role="keyword">true</phrase></code> if <code><phrase
  1336. role="special">*</phrase><phrase role="keyword">this</phrase> <phrase
  1337. role="special">!=</phrase> <phrase role="identifier">other</phrase></code>
  1338. is true and the implementation-defined total order of <code><phrase
  1339. role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
  1340. role="identifier">id</phrase></code> values places <code><phrase role="special">*</phrase><phrase
  1341. role="keyword">this</phrase></code> before <code><phrase role="identifier">other</phrase></code>,
  1342. false otherwise.
  1343. </para>
  1344. </listitem>
  1345. </varlistentry>
  1346. <varlistentry>
  1347. <term>Throws:</term>
  1348. <listitem>
  1349. <para>
  1350. Nothing.
  1351. </para>
  1352. </listitem>
  1353. </varlistentry>
  1354. </variablelist>
  1355. <para>
  1356. <bridgehead renderas="sect4" id="id_operator_greater_bridgehead">
  1357. <phrase id="id_operator_greater"/>
  1358. <link linkend="id_operator_greater">Member
  1359. function <code>operator&gt;</code>()</link>
  1360. </bridgehead>
  1361. </para>
  1362. <programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&gt;(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1363. </programlisting>
  1364. <variablelist>
  1365. <title></title>
  1366. <varlistentry>
  1367. <term>Returns:</term>
  1368. <listitem>
  1369. <para>
  1370. <code><phrase role="identifier">other</phrase> <phrase role="special">&lt;</phrase>
  1371. <phrase role="special">*</phrase> <phrase role="keyword">this</phrase></code>
  1372. </para>
  1373. </listitem>
  1374. </varlistentry>
  1375. <varlistentry>
  1376. <term>Throws:</term>
  1377. <listitem>
  1378. <para>
  1379. Nothing.
  1380. </para>
  1381. </listitem>
  1382. </varlistentry>
  1383. </variablelist>
  1384. <para>
  1385. <bridgehead renderas="sect4" id="id_operator_less_equal_bridgehead">
  1386. <phrase id="id_operator_less_equal"/>
  1387. <link linkend="id_operator_less_equal">Member
  1388. function <code>operator&lt;=</code>()</link>
  1389. </bridgehead>
  1390. </para>
  1391. <programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1392. </programlisting>
  1393. <variablelist>
  1394. <title></title>
  1395. <varlistentry>
  1396. <term>Returns:</term>
  1397. <listitem>
  1398. <para>
  1399. <code><phrase role="special">!</phrase> <phrase role="special">(</phrase><phrase
  1400. role="identifier">other</phrase> <phrase role="special">&lt;</phrase>
  1401. <phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase
  1402. role="special">)</phrase></code>
  1403. </para>
  1404. </listitem>
  1405. </varlistentry>
  1406. <varlistentry>
  1407. <term>Throws:</term>
  1408. <listitem>
  1409. <para>
  1410. Nothing.
  1411. </para>
  1412. </listitem>
  1413. </varlistentry>
  1414. </variablelist>
  1415. <para>
  1416. <bridgehead renderas="sect4" id="id_operator_greater_equal_bridgehead">
  1417. <phrase id="id_operator_greater_equal"/>
  1418. <link linkend="id_operator_greater_equal">Member
  1419. function <code>operator&gt;=</code>()</link>
  1420. </bridgehead>
  1421. </para>
  1422. <programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&gt;=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1423. </programlisting>
  1424. <variablelist>
  1425. <title></title>
  1426. <varlistentry>
  1427. <term>Returns:</term>
  1428. <listitem>
  1429. <para>
  1430. <code><phrase role="special">!</phrase> <phrase role="special">(*</phrase>
  1431. <phrase role="keyword">this</phrase> <phrase role="special">&lt;</phrase>
  1432. <phrase role="identifier">other</phrase><phrase role="special">)</phrase></code>
  1433. </para>
  1434. </listitem>
  1435. </varlistentry>
  1436. <varlistentry>
  1437. <term>Throws:</term>
  1438. <listitem>
  1439. <para>
  1440. Nothing.
  1441. </para>
  1442. </listitem>
  1443. </varlistentry>
  1444. </variablelist>
  1445. <bridgehead renderas="sect4" id="fiber.fiber_mgmt.id.h1">
  1446. <phrase id="fiber.fiber_mgmt.id.operator_lt__lt_"/><link linkend="fiber.fiber_mgmt.id.operator_lt__lt_">operator&lt;&lt;</link>
  1447. </bridgehead>
  1448. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">&gt;</phrase>
  1449. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase>
  1450. <phrase role="keyword">operator</phrase><phrase role="special">&lt;&lt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">os</phrase><phrase role="special">,</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
  1451. </programlisting>
  1452. <variablelist>
  1453. <title></title>
  1454. <varlistentry>
  1455. <term>Efects:</term>
  1456. <listitem>
  1457. <para>
  1458. Writes the representation of <code><phrase role="identifier">other</phrase></code>
  1459. to stream <code><phrase role="identifier">os</phrase></code>. The representation
  1460. is unspecified.
  1461. </para>
  1462. </listitem>
  1463. </varlistentry>
  1464. <varlistentry>
  1465. <term>Returns:</term>
  1466. <listitem>
  1467. <para>
  1468. <code><phrase role="identifier">os</phrase></code>
  1469. </para>
  1470. </listitem>
  1471. </varlistentry>
  1472. </variablelist>
  1473. </section>
  1474. <section id="fiber.fiber_mgmt.this_fiber">
  1475. <title><link linkend="fiber.fiber_mgmt.this_fiber">Namespace this_fiber</link></title>
  1476. <para>
  1477. In general, <code><phrase role="identifier">this_fiber</phrase></code> operations
  1478. may be called from the <quote>main</quote> fiber &mdash; the fiber on which function
  1479. <code><phrase role="identifier">main</phrase><phrase role="special">()</phrase></code>
  1480. is entered &mdash; as well as from an explicitly-launched thread&#8217;s thread-function.
  1481. That is, in many respects the main fiber on each thread can be treated like
  1482. an explicitly-launched fiber.
  1483. </para>
  1484. <programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  1485. <phrase role="keyword">namespace</phrase> <phrase role="identifier">this_fiber</phrase> <phrase role="special">{</phrase>
  1486. <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1487. <phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1488. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  1489. <phrase role="keyword">void</phrase> <phrase role="identifier">sleep_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;);</phrase>
  1490. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  1491. <phrase role="keyword">void</phrase> <phrase role="identifier">sleep_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;);</phrase>
  1492. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
  1493. <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
  1494. <phrase role="special">}}</phrase>
  1495. </programlisting>
  1496. <para>
  1497. <bridgehead renderas="sect4" id="this_fiber_get_id_bridgehead">
  1498. <phrase id="this_fiber_get_id"/>
  1499. <link linkend="this_fiber_get_id">Non-member
  1500. function <code>this_fiber::get_id()</code></link>
  1501. </bridgehead>
  1502. </para>
  1503. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">operations</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  1504. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  1505. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  1506. <phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1507. <phrase role="special">}}</phrase>
  1508. </programlisting>
  1509. <variablelist>
  1510. <title></title>
  1511. <varlistentry>
  1512. <term>Returns:</term>
  1513. <listitem>
  1514. <para>
  1515. An instance of <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
  1516. role="special">::</phrase><phrase role="identifier">id</phrase></code></link> that
  1517. represents the currently executing fiber.
  1518. </para>
  1519. </listitem>
  1520. </varlistentry>
  1521. <varlistentry>
  1522. <term>Throws:</term>
  1523. <listitem>
  1524. <para>
  1525. Nothing.
  1526. </para>
  1527. </listitem>
  1528. </varlistentry>
  1529. </variablelist>
  1530. <para>
  1531. <bridgehead renderas="sect4" id="this_fiber_sleep_until_bridgehead">
  1532. <phrase id="this_fiber_sleep_until"/>
  1533. <link linkend="this_fiber_sleep_until">Non-member
  1534. function <code>this_fiber::sleep_until()</code></link>
  1535. </bridgehead>
  1536. </para>
  1537. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">operations</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  1538. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  1539. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  1540. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  1541. <phrase role="keyword">void</phrase> <phrase role="identifier">sleep_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">);</phrase>
  1542. <phrase role="special">}}</phrase>
  1543. </programlisting>
  1544. <variablelist>
  1545. <title></title>
  1546. <varlistentry>
  1547. <term>Effects:</term>
  1548. <listitem>
  1549. <para>
  1550. Suspends the current fiber until the time point specified by <code><phrase
  1551. role="identifier">abs_time</phrase></code> has been reached.
  1552. </para>
  1553. </listitem>
  1554. </varlistentry>
  1555. <varlistentry>
  1556. <term>Throws:</term>
  1557. <listitem>
  1558. <para>
  1559. timeout-related exceptions.
  1560. </para>
  1561. </listitem>
  1562. </varlistentry>
  1563. <varlistentry>
  1564. <term>Note:</term>
  1565. <listitem>
  1566. <para>
  1567. The current fiber will not resume before <code><phrase role="identifier">abs_time</phrase></code>,
  1568. but there are no guarantees about how soon after <code><phrase role="identifier">abs_time</phrase></code>
  1569. it might resume.
  1570. </para>
  1571. </listitem>
  1572. </varlistentry>
  1573. <varlistentry>
  1574. <term>Note:</term>
  1575. <listitem>
  1576. <para>
  1577. <quote>timeout-related exceptions</quote> are as defined in the C++
  1578. Standard, section <emphasis role="bold">30.2.4 Timing specifications
  1579. [thread.req.timing]</emphasis>: <quote>A function that takes an argument
  1580. which specifies a timeout will throw if, during its execution, a clock,
  1581. time point, or time duration throws an exception. Such exceptions are
  1582. referred to as <emphasis>timeout-related exceptions.</emphasis></quote>
  1583. </para>
  1584. </listitem>
  1585. </varlistentry>
  1586. </variablelist>
  1587. <para>
  1588. <bridgehead renderas="sect4" id="this_fiber_sleep_for_bridgehead">
  1589. <phrase id="this_fiber_sleep_for"/>
  1590. <link linkend="this_fiber_sleep_for">Non-member
  1591. function <code>this_fiber::sleep_for()</code></link>
  1592. </bridgehead>
  1593. </para>
  1594. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">operations</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  1595. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  1596. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  1597. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  1598. <phrase role="keyword">void</phrase> <phrase role="identifier">sleep_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">);</phrase>
  1599. <phrase role="special">}}</phrase>
  1600. </programlisting>
  1601. <variablelist>
  1602. <title></title>
  1603. <varlistentry>
  1604. <term>Effects:</term>
  1605. <listitem>
  1606. <para>
  1607. Suspends the current fiber until the time duration specified by <code><phrase
  1608. role="identifier">rel_time</phrase></code> has elapsed.
  1609. </para>
  1610. </listitem>
  1611. </varlistentry>
  1612. <varlistentry>
  1613. <term>Throws:</term>
  1614. <listitem>
  1615. <para>
  1616. timeout-related exceptions.
  1617. </para>
  1618. </listitem>
  1619. </varlistentry>
  1620. <varlistentry>
  1621. <term>Note:</term>
  1622. <listitem>
  1623. <para>
  1624. The current fiber will not resume before <code><phrase role="identifier">rel_time</phrase></code>
  1625. has elapsed, but there are no guarantees about how soon after that
  1626. it might resume.
  1627. </para>
  1628. </listitem>
  1629. </varlistentry>
  1630. </variablelist>
  1631. <para>
  1632. <bridgehead renderas="sect4" id="this_fiber_yield_bridgehead">
  1633. <phrase id="this_fiber_yield"/>
  1634. <link linkend="this_fiber_yield">Non-member function
  1635. <code>this_fiber::yield()</code></link>
  1636. </bridgehead>
  1637. </para>
  1638. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">operations</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  1639. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  1640. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  1641. <phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  1642. <phrase role="special">}}</phrase>
  1643. </programlisting>
  1644. <variablelist>
  1645. <title></title>
  1646. <varlistentry>
  1647. <term>Effects:</term>
  1648. <listitem>
  1649. <para>
  1650. Relinquishes execution control, allowing other fibers to run.
  1651. </para>
  1652. </listitem>
  1653. </varlistentry>
  1654. <varlistentry>
  1655. <term>Throws:</term>
  1656. <listitem>
  1657. <para>
  1658. Nothing.
  1659. </para>
  1660. </listitem>
  1661. </varlistentry>
  1662. <varlistentry>
  1663. <term>Note:</term>
  1664. <listitem>
  1665. <para>
  1666. A fiber that calls <code><phrase role="identifier">yield</phrase><phrase
  1667. role="special">()</phrase></code> is not suspended: it is immediately
  1668. passed to the scheduler as ready to run.
  1669. </para>
  1670. </listitem>
  1671. </varlistentry>
  1672. </variablelist>
  1673. <para>
  1674. <bridgehead renderas="sect4" id="this_fiber_properties_bridgehead">
  1675. <phrase id="this_fiber_properties"/>
  1676. <link linkend="this_fiber_properties">Non-member
  1677. function <code>this_fiber::properties()</code></link>
  1678. </bridgehead>
  1679. </para>
  1680. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">operations</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  1681. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  1682. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  1683. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
  1684. <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
  1685. <phrase role="special">}}</phrase>
  1686. </programlisting>
  1687. <variablelist>
  1688. <title></title>
  1689. <varlistentry>
  1690. <term>Preconditions:</term>
  1691. <listitem>
  1692. <para>
  1693. <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link> has been called from
  1694. this thread with a subclass of <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> with
  1695. the same template argument <code><phrase role="identifier">PROPS</phrase></code>.
  1696. </para>
  1697. </listitem>
  1698. </varlistentry>
  1699. <varlistentry>
  1700. <term>Returns:</term>
  1701. <listitem>
  1702. <para>
  1703. a reference to the scheduler properties instance for the currently
  1704. running fiber.
  1705. </para>
  1706. </listitem>
  1707. </varlistentry>
  1708. <varlistentry>
  1709. <term>Throws:</term>
  1710. <listitem>
  1711. <para>
  1712. <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  1713. role="identifier">bad_cast</phrase></code> if <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
  1714. role="special">()</phrase></code> was called with an <code><phrase
  1715. role="identifier">algorithm_with_properties</phrase></code> subclass
  1716. with some other template parameter than <code><phrase role="identifier">PROPS</phrase></code>.
  1717. </para>
  1718. </listitem>
  1719. </varlistentry>
  1720. <varlistentry>
  1721. <term>Note:</term>
  1722. <listitem>
  1723. <para>
  1724. <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> provides
  1725. a way for a user-coded scheduler to associate extended properties,
  1726. such as priority, with a fiber instance. This function allows access
  1727. to those user-provided properties.
  1728. </para>
  1729. </listitem>
  1730. </varlistentry>
  1731. <varlistentry>
  1732. <term>Note:</term>
  1733. <listitem>
  1734. <para>
  1735. The first time this function is called from the main fiber of a thread,
  1736. it may internally yield, permitting other fibers to run.
  1737. </para>
  1738. </listitem>
  1739. </varlistentry>
  1740. <varlistentry>
  1741. <term>See also:</term>
  1742. <listitem>
  1743. <para>
  1744. <link linkend="custom">Customization</link>
  1745. </para>
  1746. </listitem>
  1747. </varlistentry>
  1748. </variablelist>
  1749. </section>
  1750. </section>
  1751. <section id="fiber.scheduling">
  1752. <title><anchor id="scheduling"/><link linkend="fiber.scheduling">Scheduling</link></title>
  1753. <para>
  1754. The fibers in a thread are coordinated by a fiber manager. Fibers trade control
  1755. cooperatively, rather than preemptively: the currently-running fiber retains
  1756. control until it invokes some operation that passes control to the manager.
  1757. Each time a fiber suspends (or yields), the fiber manager consults a scheduler
  1758. to determine which fiber will run next.
  1759. </para>
  1760. <para>
  1761. <emphasis role="bold">Boost.Fiber</emphasis> provides the fiber manager, but
  1762. the scheduler is a customization point. (See <link linkend="custom">Customization</link>.)
  1763. </para>
  1764. <para>
  1765. Each thread has its own scheduler. Different threads in a process may use different
  1766. schedulers. By default, <emphasis role="bold">Boost.Fiber</emphasis> implicitly
  1767. instantiates <link linkend="class_round_robin"><code>round_robin</code></link> as the scheduler for each thread.
  1768. </para>
  1769. <para>
  1770. You are explicitly permitted to code your own <link linkend="class_algorithm"><code>algorithm</code></link> subclass.
  1771. For the most part, your <code><phrase role="identifier">algorithm</phrase></code>
  1772. subclass need not defend against cross-thread calls: the fiber manager intercepts
  1773. and defers such calls. Most <code><phrase role="identifier">algorithm</phrase></code>
  1774. methods are only ever directly called from the thread whose fibers it is managing
  1775. &mdash; with exceptions as documented below.
  1776. </para>
  1777. <para>
  1778. Your <code><phrase role="identifier">algorithm</phrase></code> subclass is
  1779. engaged on a particular thread by calling <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link>:
  1780. </para>
  1781. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread_fn</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  1782. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">my_fiber_scheduler</phrase> <phrase role="special">&gt;();</phrase>
  1783. <phrase role="special">...</phrase>
  1784. <phrase role="special">}</phrase>
  1785. </programlisting>
  1786. <para>
  1787. A scheduler class must implement interface <link linkend="class_algorithm"><code>algorithm</code></link>. <emphasis
  1788. role="bold">Boost.Fiber</emphasis> provides schedulers: <link linkend="class_round_robin"><code>round_robin</code></link>,
  1789. <link linkend="class_work_stealing"><code>work_stealing</code></link>, <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link> and
  1790. <link linkend="class_shared_work"><code>shared_work</code></link>.
  1791. </para>
  1792. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  1793. <phrase role="comment">// thread registers itself at work-stealing scheduler</phrase>
  1794. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">);</phrase>
  1795. <phrase role="special">...</phrase>
  1796. <phrase role="special">}</phrase>
  1797. <phrase role="comment">// count of logical cpus</phrase>
  1798. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">thread_count</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">hardware_concurrency</phrase><phrase role="special">();</phrase>
  1799. <phrase role="comment">// start worker-threads first</phrase>
  1800. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">threads</phrase><phrase role="special">;</phrase>
  1801. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">1</phrase> <phrase role="comment">/* count start-thread */</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  1802. <phrase role="comment">// spawn thread</phrase>
  1803. <phrase role="identifier">threads</phrase><phrase role="special">.</phrase><phrase role="identifier">emplace_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">);</phrase>
  1804. <phrase role="special">}</phrase>
  1805. <phrase role="comment">// start-thread registers itself at work-stealing scheduler</phrase>
  1806. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">);</phrase>
  1807. <phrase role="special">...</phrase>
  1808. </programlisting>
  1809. <para>
  1810. The example spawns as many threads as <code><phrase role="identifier">std</phrase><phrase
  1811. role="special">::</phrase><phrase role="identifier">thread</phrase><phrase
  1812. role="special">::</phrase><phrase role="identifier">hardware_concurrency</phrase><phrase
  1813. role="special">()</phrase></code> returns. Each thread runs a <link linkend="class_work_stealing"><code>work_stealing</code></link> scheduler.
  1814. Each instance of this scheduler needs to know how many threads run the work-stealing
  1815. scheduler in the program. If the local queue of one thread runs out of ready
  1816. fibers, the thread tries to steal a ready fiber from another thread running
  1817. this scheduler.
  1818. </para>
  1819. <para>
  1820. <bridgehead renderas="sect4" id="class_algorithm_bridgehead">
  1821. <phrase id="class_algorithm"/>
  1822. <link linkend="class_algorithm">Class <code>algorithm</code></link>
  1823. </bridgehead>
  1824. </para>
  1825. <para>
  1826. <code><phrase role="identifier">algorithm</phrase></code> is the abstract base
  1827. class defining the interface that a fiber scheduler must implement.
  1828. </para>
  1829. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">algo</phrase><phrase role="special">/</phrase><phrase role="identifier">algorithm</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  1830. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  1831. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  1832. <phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
  1833. <phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase>
  1834. <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">algorithm</phrase><phrase role="special">();</phrase>
  1835. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  1836. <phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  1837. <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  1838. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  1839. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  1840. <phrase role="special">};</phrase>
  1841. <phrase role="special">}}}</phrase>
  1842. </programlisting>
  1843. <para>
  1844. <bridgehead renderas="sect4" id="algorithm_awakened_bridgehead">
  1845. <phrase id="algorithm_awakened"/>
  1846. <link linkend="algorithm_awakened">Member function
  1847. <code>awakened</code>()</link>
  1848. </bridgehead>
  1849. </para>
  1850. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  1851. </programlisting>
  1852. <variablelist>
  1853. <title></title>
  1854. <varlistentry>
  1855. <term>Effects:</term>
  1856. <listitem>
  1857. <para>
  1858. Informs the scheduler that fiber <code><phrase role="identifier">f</phrase></code>
  1859. is ready to run. Fiber <code><phrase role="identifier">f</phrase></code>
  1860. might be newly launched, or it might have been blocked but has just been
  1861. awakened, or it might have called <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>.
  1862. </para>
  1863. </listitem>
  1864. </varlistentry>
  1865. <varlistentry>
  1866. <term>Note:</term>
  1867. <listitem>
  1868. <para>
  1869. This method advises the scheduler to add fiber <code><phrase role="identifier">f</phrase></code>
  1870. to its collection of fibers ready to run. A typical scheduler implementation
  1871. places <code><phrase role="identifier">f</phrase></code> into a queue.
  1872. </para>
  1873. </listitem>
  1874. </varlistentry>
  1875. <varlistentry>
  1876. <term>See also:</term>
  1877. <listitem>
  1878. <para>
  1879. <link linkend="class_round_robin"><code>round_robin</code></link>
  1880. </para>
  1881. </listitem>
  1882. </varlistentry>
  1883. </variablelist>
  1884. <para>
  1885. <bridgehead renderas="sect4" id="algorithm_pick_next_bridgehead">
  1886. <phrase id="algorithm_pick_next"/>
  1887. <link linkend="algorithm_pick_next">Member
  1888. function <code>pick_next</code>()</link>
  1889. </bridgehead>
  1890. </para>
  1891. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  1892. </programlisting>
  1893. <variablelist>
  1894. <title></title>
  1895. <varlistentry>
  1896. <term>Returns:</term>
  1897. <listitem>
  1898. <para>
  1899. the fiber which is to be resumed next, or <code><phrase role="keyword">nullptr</phrase></code>
  1900. if there is no ready fiber.
  1901. </para>
  1902. </listitem>
  1903. </varlistentry>
  1904. <varlistentry>
  1905. <term>Note:</term>
  1906. <listitem>
  1907. <para>
  1908. This is where the scheduler actually specifies the fiber which is to
  1909. run next. A typical scheduler implementation chooses the head of the
  1910. ready queue.
  1911. </para>
  1912. </listitem>
  1913. </varlistentry>
  1914. <varlistentry>
  1915. <term>See also:</term>
  1916. <listitem>
  1917. <para>
  1918. <link linkend="class_round_robin"><code>round_robin</code></link>
  1919. </para>
  1920. </listitem>
  1921. </varlistentry>
  1922. </variablelist>
  1923. <para>
  1924. <bridgehead renderas="sect4" id="algorithm_has_ready_fibers_bridgehead">
  1925. <phrase id="algorithm_has_ready_fibers"/>
  1926. <link linkend="algorithm_has_ready_fibers">Member
  1927. function <code>has_ready_fibers</code>()</link>
  1928. </bridgehead>
  1929. </para>
  1930. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  1931. </programlisting>
  1932. <variablelist>
  1933. <title></title>
  1934. <varlistentry>
  1935. <term>Returns:</term>
  1936. <listitem>
  1937. <para>
  1938. <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
  1939. ready to run.
  1940. </para>
  1941. </listitem>
  1942. </varlistentry>
  1943. </variablelist>
  1944. <para>
  1945. <bridgehead renderas="sect4" id="algorithm_suspend_until_bridgehead">
  1946. <phrase id="algorithm_suspend_until"/>
  1947. <link linkend="algorithm_suspend_until">Member
  1948. function <code>suspend_until</code>()</link>
  1949. </bridgehead>
  1950. </para>
  1951. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  1952. </programlisting>
  1953. <variablelist>
  1954. <title></title>
  1955. <varlistentry>
  1956. <term>Effects:</term>
  1957. <listitem>
  1958. <para>
  1959. Informs the scheduler that no fiber will be ready until time-point <code><phrase
  1960. role="identifier">abs_time</phrase></code>.
  1961. </para>
  1962. </listitem>
  1963. </varlistentry>
  1964. <varlistentry>
  1965. <term>Note:</term>
  1966. <listitem>
  1967. <para>
  1968. This method allows a custom scheduler to yield control to the containing
  1969. environment in whatever way makes sense. The fiber manager is stating
  1970. that <code><phrase role="identifier">suspend_until</phrase><phrase role="special">()</phrase></code>
  1971. need not return until <code><phrase role="identifier">abs_time</phrase></code>
  1972. &mdash; or <link linkend="algorithm_notify"><code>algorithm::notify()</code></link> is called &mdash; whichever comes first.
  1973. The interaction with <code><phrase role="identifier">notify</phrase><phrase
  1974. role="special">()</phrase></code> means that, for instance, calling
  1975. <ulink url="http://en.cppreference.com/w/cpp/thread/sleep_until"><code><phrase
  1976. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  1977. role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase
  1978. role="identifier">sleep_until</phrase><phrase role="special">(</phrase><phrase
  1979. role="identifier">abs_time</phrase><phrase role="special">)</phrase></code></ulink>
  1980. would be too simplistic. <link linkend="round_robin_suspend_until"><code>round_robin::suspend_until()</code></link> uses
  1981. a <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable"><code><phrase
  1982. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  1983. role="identifier">condition_variable</phrase></code></ulink> to coordinate
  1984. with <link linkend="round_robin_notify"><code>round_robin::notify()</code></link>.
  1985. </para>
  1986. </listitem>
  1987. </varlistentry>
  1988. <varlistentry>
  1989. <term>Note:</term>
  1990. <listitem>
  1991. <para>
  1992. Given that <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code>
  1993. might be called from another thread, your <code><phrase role="identifier">suspend_until</phrase><phrase
  1994. role="special">()</phrase></code> implementation &mdash; like the rest of your
  1995. <code><phrase role="identifier">algorithm</phrase></code> implementation
  1996. &mdash; must guard any data it shares with your <code><phrase role="identifier">notify</phrase><phrase
  1997. role="special">()</phrase></code> implementation.
  1998. </para>
  1999. </listitem>
  2000. </varlistentry>
  2001. </variablelist>
  2002. <para>
  2003. <bridgehead renderas="sect4" id="algorithm_notify_bridgehead">
  2004. <phrase id="algorithm_notify"/>
  2005. <link linkend="algorithm_notify">Member function
  2006. <code>notify</code>()</link>
  2007. </bridgehead>
  2008. </para>
  2009. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  2010. </programlisting>
  2011. <variablelist>
  2012. <title></title>
  2013. <varlistentry>
  2014. <term>Effects:</term>
  2015. <listitem>
  2016. <para>
  2017. Requests the scheduler to return from a pending call to <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>.
  2018. </para>
  2019. </listitem>
  2020. </varlistentry>
  2021. <varlistentry>
  2022. <term>Note:</term>
  2023. <listitem>
  2024. <para>
  2025. Alone among the <code><phrase role="identifier">algorithm</phrase></code>
  2026. methods, <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code>
  2027. may be called from another thread. Your <code><phrase role="identifier">notify</phrase><phrase
  2028. role="special">()</phrase></code> implementation must guard any data
  2029. it shares with the rest of your <code><phrase role="identifier">algorithm</phrase></code>
  2030. implementation.
  2031. </para>
  2032. </listitem>
  2033. </varlistentry>
  2034. </variablelist>
  2035. <para>
  2036. <bridgehead renderas="sect4" id="class_round_robin_bridgehead">
  2037. <phrase id="class_round_robin"/>
  2038. <link linkend="class_round_robin">Class <code>round_robin</code></link>
  2039. </bridgehead>
  2040. </para>
  2041. <para>
  2042. This class implements <link linkend="class_algorithm"><code>algorithm</code></link>, scheduling fibers in round-robin
  2043. fashion.
  2044. </para>
  2045. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">algo</phrase><phrase role="special">/</phrase><phrase role="identifier">round_robin</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  2046. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  2047. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  2048. <phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
  2049. <phrase role="keyword">class</phrase> <phrase role="identifier">round_robin</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase>
  2050. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2051. <phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2052. <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2053. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2054. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2055. <phrase role="special">};</phrase>
  2056. <phrase role="special">}}}</phrase>
  2057. </programlisting>
  2058. <para>
  2059. <bridgehead renderas="sect4" id="round_robin_awakened_bridgehead">
  2060. <phrase id="round_robin_awakened"/>
  2061. <link linkend="round_robin_awakened">Member
  2062. function <code>awakened</code>()</link>
  2063. </bridgehead>
  2064. </para>
  2065. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2066. </programlisting>
  2067. <variablelist>
  2068. <title></title>
  2069. <varlistentry>
  2070. <term>Effects:</term>
  2071. <listitem>
  2072. <para>
  2073. Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto
  2074. a ready queue.
  2075. </para>
  2076. </listitem>
  2077. </varlistentry>
  2078. <varlistentry>
  2079. <term>Throws:</term>
  2080. <listitem>
  2081. <para>
  2082. Nothing.
  2083. </para>
  2084. </listitem>
  2085. </varlistentry>
  2086. </variablelist>
  2087. <para>
  2088. <bridgehead renderas="sect4" id="round_robin_pick_next_bridgehead">
  2089. <phrase id="round_robin_pick_next"/>
  2090. <link linkend="round_robin_pick_next">Member
  2091. function <code>pick_next</code>()</link>
  2092. </bridgehead>
  2093. </para>
  2094. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2095. </programlisting>
  2096. <variablelist>
  2097. <title></title>
  2098. <varlistentry>
  2099. <term>Returns:</term>
  2100. <listitem>
  2101. <para>
  2102. the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code>
  2103. if the queue is empty.
  2104. </para>
  2105. </listitem>
  2106. </varlistentry>
  2107. <varlistentry>
  2108. <term>Throws:</term>
  2109. <listitem>
  2110. <para>
  2111. Nothing.
  2112. </para>
  2113. </listitem>
  2114. </varlistentry>
  2115. <varlistentry>
  2116. <term>Note:</term>
  2117. <listitem>
  2118. <para>
  2119. Placing ready fibers onto the tail of a queue, and returning them from
  2120. the head of that queue, shares the thread between ready fibers in round-robin
  2121. fashion.
  2122. </para>
  2123. </listitem>
  2124. </varlistentry>
  2125. </variablelist>
  2126. <para>
  2127. <bridgehead renderas="sect4" id="round_robin_has_ready_fibers_bridgehead">
  2128. <phrase id="round_robin_has_ready_fibers"/>
  2129. <link linkend="round_robin_has_ready_fibers">Member
  2130. function <code>has_ready_fibers</code>()</link>
  2131. </bridgehead>
  2132. </para>
  2133. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2134. </programlisting>
  2135. <variablelist>
  2136. <title></title>
  2137. <varlistentry>
  2138. <term>Returns:</term>
  2139. <listitem>
  2140. <para>
  2141. <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
  2142. ready to run.
  2143. </para>
  2144. </listitem>
  2145. </varlistentry>
  2146. <varlistentry>
  2147. <term>Throws:</term>
  2148. <listitem>
  2149. <para>
  2150. Nothing.
  2151. </para>
  2152. </listitem>
  2153. </varlistentry>
  2154. </variablelist>
  2155. <para>
  2156. <bridgehead renderas="sect4" id="round_robin_suspend_until_bridgehead">
  2157. <phrase id="round_robin_suspend_until"/>
  2158. <link linkend="round_robin_suspend_until">Member
  2159. function <code>suspend_until</code>()</link>
  2160. </bridgehead>
  2161. </para>
  2162. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2163. </programlisting>
  2164. <variablelist>
  2165. <title></title>
  2166. <varlistentry>
  2167. <term>Effects:</term>
  2168. <listitem>
  2169. <para>
  2170. Informs <code><phrase role="identifier">round_robin</phrase></code> that
  2171. no ready fiber will be available until time-point <code><phrase role="identifier">abs_time</phrase></code>.
  2172. This implementation blocks in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
  2173. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  2174. role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
  2175. role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
  2176. </para>
  2177. </listitem>
  2178. </varlistentry>
  2179. <varlistentry>
  2180. <term>Throws:</term>
  2181. <listitem>
  2182. <para>
  2183. Nothing.
  2184. </para>
  2185. </listitem>
  2186. </varlistentry>
  2187. </variablelist>
  2188. <para>
  2189. <bridgehead renderas="sect4" id="round_robin_notify_bridgehead">
  2190. <phrase id="round_robin_notify"/>
  2191. <link linkend="round_robin_notify">Member function
  2192. <code>notify</code>()</link>
  2193. </bridgehead>
  2194. </para>
  2195. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  2196. </programlisting>
  2197. <variablelist>
  2198. <title></title>
  2199. <varlistentry>
  2200. <term>Effects:</term>
  2201. <listitem>
  2202. <para>
  2203. Wake up a pending call to <link linkend="round_robin_suspend_until"><code>round_robin::suspend_until()</code></link>,
  2204. some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
  2205. role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
  2206. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  2207. role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
  2208. role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
  2209. </para>
  2210. </listitem>
  2211. </varlistentry>
  2212. <varlistentry>
  2213. <term>Throws:</term>
  2214. <listitem>
  2215. <para>
  2216. Nothing.
  2217. </para>
  2218. </listitem>
  2219. </varlistentry>
  2220. </variablelist>
  2221. <para>
  2222. <bridgehead renderas="sect4" id="class_work_stealing_bridgehead">
  2223. <phrase id="class_work_stealing"/>
  2224. <link linkend="class_work_stealing">Class <code>work_stealing</code></link>
  2225. </bridgehead>
  2226. </para>
  2227. <para>
  2228. This class implements <link linkend="class_algorithm"><code>algorithm</code></link>; if the local ready-queue runs
  2229. out of ready fibers, ready fibers are stolen from other schedulers.<sbr/> The
  2230. victim scheduler (from which a ready fiber is stolen) is selected at random.
  2231. </para>
  2232. <note>
  2233. <para>
  2234. Worker-threads are stored in a static variable, dynamically adding/removing
  2235. worker threads is not supported.
  2236. </para>
  2237. </note>
  2238. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">algo</phrase><phrase role="special">/</phrase><phrase role="identifier">work_stealing</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  2239. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  2240. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  2241. <phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
  2242. <phrase role="keyword">class</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase>
  2243. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  2244. <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase>
  2245. <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  2246. <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  2247. <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  2248. <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  2249. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2250. <phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2251. <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2252. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2253. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2254. <phrase role="special">};</phrase>
  2255. <phrase role="special">}}}</phrase>
  2256. </programlisting>
  2257. <bridgehead renderas="sect3" id="fiber.scheduling.h0">
  2258. <phrase id="fiber.scheduling.constructor"/><link linkend="fiber.scheduling.constructor">Constructor</link>
  2259. </bridgehead>
  2260. <programlisting><phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase>
  2261. </programlisting>
  2262. <variablelist>
  2263. <title></title>
  2264. <varlistentry>
  2265. <term>Effects:</term>
  2266. <listitem>
  2267. <para>
  2268. Constructs work-stealing scheduling algorithm. <code><phrase role="identifier">thread_count</phrase></code>
  2269. represents the number of threads running this algorithm.
  2270. </para>
  2271. </listitem>
  2272. </varlistentry>
  2273. <varlistentry>
  2274. <term>Throws:</term>
  2275. <listitem>
  2276. <para>
  2277. <code><phrase role="identifier">system_error</phrase></code>
  2278. </para>
  2279. </listitem>
  2280. </varlistentry>
  2281. <varlistentry>
  2282. <term>Note:</term>
  2283. <listitem>
  2284. <para>
  2285. If <code><phrase role="identifier">suspend</phrase></code> is set to
  2286. <code><phrase role="keyword">true</phrase></code>, then the scheduler
  2287. suspends if no ready fiber could be stolen. The scheduler will by woken
  2288. up if a sleeping fiber times out or it was notified from remote (other
  2289. thread or fiber scheduler).
  2290. </para>
  2291. </listitem>
  2292. </varlistentry>
  2293. </variablelist>
  2294. <para>
  2295. <bridgehead renderas="sect4" id="work_stealing_awakened_bridgehead">
  2296. <phrase id="work_stealing_awakened"/>
  2297. <link linkend="work_stealing_awakened">Member
  2298. function <code>awakened</code>()</link>
  2299. </bridgehead>
  2300. </para>
  2301. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2302. </programlisting>
  2303. <variablelist>
  2304. <title></title>
  2305. <varlistentry>
  2306. <term>Effects:</term>
  2307. <listitem>
  2308. <para>
  2309. Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto
  2310. the shared ready queue.
  2311. </para>
  2312. </listitem>
  2313. </varlistentry>
  2314. <varlistentry>
  2315. <term>Throws:</term>
  2316. <listitem>
  2317. <para>
  2318. Nothing.
  2319. </para>
  2320. </listitem>
  2321. </varlistentry>
  2322. </variablelist>
  2323. <para>
  2324. <bridgehead renderas="sect4" id="work_stealing_pick_next_bridgehead">
  2325. <phrase id="work_stealing_pick_next"/>
  2326. <link linkend="work_stealing_pick_next">Member
  2327. function <code>pick_next</code>()</link>
  2328. </bridgehead>
  2329. </para>
  2330. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2331. </programlisting>
  2332. <variablelist>
  2333. <title></title>
  2334. <varlistentry>
  2335. <term>Returns:</term>
  2336. <listitem>
  2337. <para>
  2338. the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code>
  2339. if the queue is empty.
  2340. </para>
  2341. </listitem>
  2342. </varlistentry>
  2343. <varlistentry>
  2344. <term>Throws:</term>
  2345. <listitem>
  2346. <para>
  2347. Nothing.
  2348. </para>
  2349. </listitem>
  2350. </varlistentry>
  2351. <varlistentry>
  2352. <term>Note:</term>
  2353. <listitem>
  2354. <para>
  2355. Placing ready fibers onto the tail of the sahred queue, and returning
  2356. them from the head of that queue, shares the thread between ready fibers
  2357. in round-robin fashion.
  2358. </para>
  2359. </listitem>
  2360. </varlistentry>
  2361. </variablelist>
  2362. <para>
  2363. <bridgehead renderas="sect4" id="work_stealing_has_ready_fibers_bridgehead">
  2364. <phrase id="work_stealing_has_ready_fibers"/>
  2365. <link linkend="work_stealing_has_ready_fibers">Member
  2366. function <code>has_ready_fibers</code>()</link>
  2367. </bridgehead>
  2368. </para>
  2369. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2370. </programlisting>
  2371. <variablelist>
  2372. <title></title>
  2373. <varlistentry>
  2374. <term>Returns:</term>
  2375. <listitem>
  2376. <para>
  2377. <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
  2378. ready to run.
  2379. </para>
  2380. </listitem>
  2381. </varlistentry>
  2382. <varlistentry>
  2383. <term>Throws:</term>
  2384. <listitem>
  2385. <para>
  2386. Nothing.
  2387. </para>
  2388. </listitem>
  2389. </varlistentry>
  2390. </variablelist>
  2391. <para>
  2392. <bridgehead renderas="sect4" id="work_stealing_suspend_until_bridgehead">
  2393. <phrase id="work_stealing_suspend_until"/>
  2394. <link linkend="work_stealing_suspend_until">Member
  2395. function <code>suspend_until</code>()</link>
  2396. </bridgehead>
  2397. </para>
  2398. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2399. </programlisting>
  2400. <variablelist>
  2401. <title></title>
  2402. <varlistentry>
  2403. <term>Effects:</term>
  2404. <listitem>
  2405. <para>
  2406. Informs <code><phrase role="identifier">work_stealing</phrase></code>
  2407. that no ready fiber will be available until time-point <code><phrase
  2408. role="identifier">abs_time</phrase></code>. This implementation blocks
  2409. in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
  2410. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  2411. role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
  2412. role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
  2413. </para>
  2414. </listitem>
  2415. </varlistentry>
  2416. <varlistentry>
  2417. <term>Throws:</term>
  2418. <listitem>
  2419. <para>
  2420. Nothing.
  2421. </para>
  2422. </listitem>
  2423. </varlistentry>
  2424. </variablelist>
  2425. <para>
  2426. <bridgehead renderas="sect4" id="work_stealing_notify_bridgehead">
  2427. <phrase id="work_stealing_notify"/>
  2428. <link linkend="work_stealing_notify">Member
  2429. function <code>notify</code>()</link>
  2430. </bridgehead>
  2431. </para>
  2432. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  2433. </programlisting>
  2434. <variablelist>
  2435. <title></title>
  2436. <varlistentry>
  2437. <term>Effects:</term>
  2438. <listitem>
  2439. <para>
  2440. Wake up a pending call to <link linkend="work_stealing_suspend_until"><code>work_stealing::suspend_until()</code></link>,
  2441. some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
  2442. role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
  2443. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  2444. role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
  2445. role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
  2446. </para>
  2447. </listitem>
  2448. </varlistentry>
  2449. <varlistentry>
  2450. <term>Throws:</term>
  2451. <listitem>
  2452. <para>
  2453. Nothing.
  2454. </para>
  2455. </listitem>
  2456. </varlistentry>
  2457. </variablelist>
  2458. <para>
  2459. <bridgehead renderas="sect4" id="class_shared_work_bridgehead">
  2460. <phrase id="class_shared_work"/>
  2461. <link linkend="class_shared_work">Class <code>shared_work</code></link>
  2462. </bridgehead>
  2463. </para>
  2464. <note>
  2465. <para>
  2466. Because of the non-locality of data, <emphasis>shared_work</emphasis> is
  2467. less performant than <link linkend="class_work_stealing"><code>work_stealing</code></link>.
  2468. </para>
  2469. </note>
  2470. <para>
  2471. This class implements <link linkend="class_algorithm"><code>algorithm</code></link>, scheduling fibers in round-robin
  2472. fashion. Ready fibers are shared between all instances (running on different
  2473. threads) of shared_work, thus the work is distributed equally over all threads.
  2474. </para>
  2475. <note>
  2476. <para>
  2477. Worker-threads are stored in a static variable, dynamically adding/removing
  2478. worker threads is not supported.
  2479. </para>
  2480. </note>
  2481. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">algo</phrase><phrase role="special">/</phrase><phrase role="identifier">shared_work</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  2482. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  2483. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  2484. <phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
  2485. <phrase role="keyword">class</phrase> <phrase role="identifier">shared_work</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase>
  2486. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2487. <phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2488. <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2489. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2490. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2491. <phrase role="special">};</phrase>
  2492. <phrase role="special">}}}</phrase>
  2493. </programlisting>
  2494. <para>
  2495. <bridgehead renderas="sect4" id="shared_work_awakened_bridgehead">
  2496. <phrase id="shared_work_awakened"/>
  2497. <link linkend="shared_work_awakened">Member
  2498. function <code>awakened</code>()</link>
  2499. </bridgehead>
  2500. </para>
  2501. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2502. </programlisting>
  2503. <variablelist>
  2504. <title></title>
  2505. <varlistentry>
  2506. <term>Effects:</term>
  2507. <listitem>
  2508. <para>
  2509. Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto
  2510. the shared ready queue.
  2511. </para>
  2512. </listitem>
  2513. </varlistentry>
  2514. <varlistentry>
  2515. <term>Throws:</term>
  2516. <listitem>
  2517. <para>
  2518. Nothing.
  2519. </para>
  2520. </listitem>
  2521. </varlistentry>
  2522. </variablelist>
  2523. <para>
  2524. <bridgehead renderas="sect4" id="shared_work_pick_next_bridgehead">
  2525. <phrase id="shared_work_pick_next"/>
  2526. <link linkend="shared_work_pick_next">Member
  2527. function <code>pick_next</code>()</link>
  2528. </bridgehead>
  2529. </para>
  2530. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2531. </programlisting>
  2532. <variablelist>
  2533. <title></title>
  2534. <varlistentry>
  2535. <term>Returns:</term>
  2536. <listitem>
  2537. <para>
  2538. the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code>
  2539. if the queue is empty.
  2540. </para>
  2541. </listitem>
  2542. </varlistentry>
  2543. <varlistentry>
  2544. <term>Throws:</term>
  2545. <listitem>
  2546. <para>
  2547. Nothing.
  2548. </para>
  2549. </listitem>
  2550. </varlistentry>
  2551. <varlistentry>
  2552. <term>Note:</term>
  2553. <listitem>
  2554. <para>
  2555. Placing ready fibers onto the tail of the shared queue, and returning
  2556. them from the head of that queue, shares the thread between ready fibers
  2557. in round-robin fashion.
  2558. </para>
  2559. </listitem>
  2560. </varlistentry>
  2561. </variablelist>
  2562. <para>
  2563. <bridgehead renderas="sect4" id="shared_work_has_ready_fibers_bridgehead">
  2564. <phrase id="shared_work_has_ready_fibers"/>
  2565. <link linkend="shared_work_has_ready_fibers">Member
  2566. function <code>has_ready_fibers</code>()</link>
  2567. </bridgehead>
  2568. </para>
  2569. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2570. </programlisting>
  2571. <variablelist>
  2572. <title></title>
  2573. <varlistentry>
  2574. <term>Returns:</term>
  2575. <listitem>
  2576. <para>
  2577. <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
  2578. ready to run.
  2579. </para>
  2580. </listitem>
  2581. </varlistentry>
  2582. <varlistentry>
  2583. <term>Throws:</term>
  2584. <listitem>
  2585. <para>
  2586. Nothing.
  2587. </para>
  2588. </listitem>
  2589. </varlistentry>
  2590. </variablelist>
  2591. <para>
  2592. <bridgehead renderas="sect4" id="shared_work_suspend_until_bridgehead">
  2593. <phrase id="shared_work_suspend_until"/>
  2594. <link linkend="shared_work_suspend_until">Member
  2595. function <code>suspend_until</code>()</link>
  2596. </bridgehead>
  2597. </para>
  2598. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2599. </programlisting>
  2600. <variablelist>
  2601. <title></title>
  2602. <varlistentry>
  2603. <term>Effects:</term>
  2604. <listitem>
  2605. <para>
  2606. Informs <code><phrase role="identifier">shared_work</phrase></code> that
  2607. no ready fiber will be available until time-point <code><phrase role="identifier">abs_time</phrase></code>.
  2608. This implementation blocks in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
  2609. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  2610. role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
  2611. role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
  2612. </para>
  2613. </listitem>
  2614. </varlistentry>
  2615. <varlistentry>
  2616. <term>Throws:</term>
  2617. <listitem>
  2618. <para>
  2619. Nothing.
  2620. </para>
  2621. </listitem>
  2622. </varlistentry>
  2623. </variablelist>
  2624. <para>
  2625. <bridgehead renderas="sect4" id="shared_work_notify_bridgehead">
  2626. <phrase id="shared_work_notify"/>
  2627. <link linkend="shared_work_notify">Member function
  2628. <code>notify</code>()</link>
  2629. </bridgehead>
  2630. </para>
  2631. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  2632. </programlisting>
  2633. <variablelist>
  2634. <title></title>
  2635. <varlistentry>
  2636. <term>Effects:</term>
  2637. <listitem>
  2638. <para>
  2639. Wake up a pending call to <link linkend="shared_work_suspend_until"><code>shared_work::suspend_until()</code></link>,
  2640. some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
  2641. role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
  2642. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  2643. role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
  2644. role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
  2645. </para>
  2646. </listitem>
  2647. </varlistentry>
  2648. <varlistentry>
  2649. <term>Throws:</term>
  2650. <listitem>
  2651. <para>
  2652. Nothing.
  2653. </para>
  2654. </listitem>
  2655. </varlistentry>
  2656. </variablelist>
  2657. <bridgehead renderas="sect3" id="fiber.scheduling.h1">
  2658. <phrase id="fiber.scheduling.custom_scheduler_fiber_properties"/><link linkend="fiber.scheduling.custom_scheduler_fiber_properties">Custom
  2659. Scheduler Fiber Properties</link>
  2660. </bridgehead>
  2661. <para>
  2662. A scheduler class directly derived from <link linkend="class_algorithm"><code>algorithm</code></link> can use any
  2663. information available from <link linkend="class_context"><code>context</code></link> to implement the <code><phrase
  2664. role="identifier">algorithm</phrase></code> interface. But a custom scheduler
  2665. might need to track additional properties for a fiber. For instance, a priority-based
  2666. scheduler would need to track a fiber&#8217;s priority.
  2667. </para>
  2668. <para>
  2669. <emphasis role="bold">Boost.Fiber</emphasis> provides a mechanism by which
  2670. your custom scheduler can associate custom properties with each fiber.
  2671. </para>
  2672. <para>
  2673. <bridgehead renderas="sect4" id="class_fiber_properties_bridgehead">
  2674. <phrase id="class_fiber_properties"/>
  2675. <link linkend="class_fiber_properties">Class
  2676. <code>fiber_properties</code></link>
  2677. </bridgehead>
  2678. </para>
  2679. <para>
  2680. A custom fiber properties class must be derived from <code><phrase role="identifier">fiber_properties</phrase></code>.
  2681. </para>
  2682. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">properties</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  2683. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  2684. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  2685. <phrase role="keyword">class</phrase> <phrase role="identifier">fiber_properties</phrase> <phrase role="special">{</phrase>
  2686. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  2687. <phrase role="identifier">fiber_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2688. <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">fiber_properties</phrase><phrase role="special">();</phrase>
  2689. <phrase role="keyword">protected</phrase><phrase role="special">:</phrase>
  2690. <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2691. <phrase role="special">};</phrase>
  2692. <phrase role="special">}}</phrase>
  2693. </programlisting>
  2694. <bridgehead renderas="sect3" id="fiber.scheduling.h2">
  2695. <phrase id="fiber.scheduling.constructor0"/><link linkend="fiber.scheduling.constructor0">Constructor</link>
  2696. </bridgehead>
  2697. <programlisting><phrase role="identifier">fiber_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2698. </programlisting>
  2699. <variablelist>
  2700. <title></title>
  2701. <varlistentry>
  2702. <term>Effects:</term>
  2703. <listitem>
  2704. <para>
  2705. Constructs base-class component of custom subclass.
  2706. </para>
  2707. </listitem>
  2708. </varlistentry>
  2709. <varlistentry>
  2710. <term>Throws:</term>
  2711. <listitem>
  2712. <para>
  2713. Nothing.
  2714. </para>
  2715. </listitem>
  2716. </varlistentry>
  2717. <varlistentry>
  2718. <term>Note:</term>
  2719. <listitem>
  2720. <para>
  2721. Your subclass constructor must accept a <code><phrase role="identifier">context</phrase><phrase
  2722. role="special">*</phrase></code> and pass it to the base-class <code><phrase
  2723. role="identifier">fiber_properties</phrase></code> constructor.
  2724. </para>
  2725. </listitem>
  2726. </varlistentry>
  2727. </variablelist>
  2728. <para>
  2729. <bridgehead renderas="sect4" id="fiber_properties_notify_bridgehead">
  2730. <phrase id="fiber_properties_notify"/>
  2731. <link linkend="fiber_properties_notify">Member
  2732. function <code>notify</code>()</link>
  2733. </bridgehead>
  2734. </para>
  2735. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2736. </programlisting>
  2737. <variablelist>
  2738. <title></title>
  2739. <varlistentry>
  2740. <term>Effects:</term>
  2741. <listitem>
  2742. <para>
  2743. Pass control to the custom <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> subclass&#8217;s
  2744. <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link> method.
  2745. </para>
  2746. </listitem>
  2747. </varlistentry>
  2748. <varlistentry>
  2749. <term>Throws:</term>
  2750. <listitem>
  2751. <para>
  2752. Nothing.
  2753. </para>
  2754. </listitem>
  2755. </varlistentry>
  2756. <varlistentry>
  2757. <term>Note:</term>
  2758. <listitem>
  2759. <para>
  2760. A custom scheduler&#8217;s <link linkend="algorithm_with_properties_pick_next"><code>algorithm_with_properties::pick_next()</code></link> method
  2761. might dynamically select from the ready fibers, or <link linkend="algorithm_with_properties_awakened"><code>algorithm_with_properties::awakened()</code></link> might
  2762. instead insert each ready fiber into some form of ready queue for <code><phrase
  2763. role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>.
  2764. In the latter case, if application code modifies a fiber property (e.g.
  2765. priority) that should affect that fiber&#8217;s relationship to other ready
  2766. fibers, the custom scheduler must be given the opportunity to reorder
  2767. its ready queue. The custom property subclass should implement an access
  2768. method to modify such a property; that access method should call <code><phrase
  2769. role="identifier">notify</phrase><phrase role="special">()</phrase></code>
  2770. once the new property value has been stored. This passes control to the
  2771. custom scheduler&#8217;s <code><phrase role="identifier">property_change</phrase><phrase
  2772. role="special">()</phrase></code> method, allowing the custom scheduler
  2773. to reorder its ready queue appropriately. Use at your discretion. Of
  2774. course, if you define a property which does not affect the behavior of
  2775. the <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>
  2776. method, you need not call <code><phrase role="identifier">notify</phrase><phrase
  2777. role="special">()</phrase></code> when that property is modified.
  2778. </para>
  2779. </listitem>
  2780. </varlistentry>
  2781. </variablelist>
  2782. <para>
  2783. <bridgehead renderas="sect4" id="class_algorithm_with_properties_bridgehead">
  2784. <phrase id="class_algorithm_with_properties"/>
  2785. <link linkend="class_algorithm_with_properties">Template
  2786. <code>algorithm_with_properties&lt;&gt;</code></link>
  2787. </bridgehead>
  2788. </para>
  2789. <para>
  2790. A custom scheduler that depends on a custom properties class <code><phrase
  2791. role="identifier">PROPS</phrase></code> should be derived from <code><phrase
  2792. role="identifier">algorithm_with_properties</phrase><phrase role="special">&lt;</phrase><phrase
  2793. role="identifier">PROPS</phrase><phrase role="special">&gt;</phrase></code>.
  2794. <code><phrase role="identifier">PROPS</phrase></code> should be derived from
  2795. <link linkend="class_fiber_properties"><code>fiber_properties</code></link>.
  2796. </para>
  2797. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">algorithm</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  2798. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  2799. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  2800. <phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
  2801. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
  2802. <phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm_with_properties</phrase> <phrase role="special">{</phrase>
  2803. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*,</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  2804. <phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2805. <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2806. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  2807. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  2808. <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2809. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">property_change</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*,</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2810. <phrase role="keyword">virtual</phrase> <phrase role="identifier">fiber_properties</phrase> <phrase role="special">*</phrase> <phrase role="identifier">new_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*);</phrase>
  2811. <phrase role="special">};</phrase>
  2812. <phrase role="special">}}}</phrase>
  2813. </programlisting>
  2814. <para>
  2815. <bridgehead renderas="sect4" id="algorithm_with_properties_awakened_bridgehead">
  2816. <phrase id="algorithm_with_properties_awakened"/>
  2817. <link linkend="algorithm_with_properties_awakened">Member
  2818. function <code>awakened</code>()</link>
  2819. </bridgehead>
  2820. </para>
  2821. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">,</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2822. </programlisting>
  2823. <variablelist>
  2824. <title></title>
  2825. <varlistentry>
  2826. <term>Effects:</term>
  2827. <listitem>
  2828. <para>
  2829. Informs the scheduler that fiber <code><phrase role="identifier">f</phrase></code>
  2830. is ready to run, like <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>. Passes
  2831. the fiber&#8217;s associated <code><phrase role="identifier">PROPS</phrase></code>
  2832. instance.
  2833. </para>
  2834. </listitem>
  2835. </varlistentry>
  2836. <varlistentry>
  2837. <term>Throws:</term>
  2838. <listitem>
  2839. <para>
  2840. Nothing.
  2841. </para>
  2842. </listitem>
  2843. </varlistentry>
  2844. <varlistentry>
  2845. <term>Note:</term>
  2846. <listitem>
  2847. <para>
  2848. An <code><phrase role="identifier">algorithm_with_properties</phrase><phrase
  2849. role="special">&lt;&gt;</phrase></code> subclass must override this method
  2850. instead of <code><phrase role="identifier">algorithm</phrase><phrase
  2851. role="special">::</phrase><phrase role="identifier">awakened</phrase><phrase
  2852. role="special">()</phrase></code>.
  2853. </para>
  2854. </listitem>
  2855. </varlistentry>
  2856. </variablelist>
  2857. <para>
  2858. <bridgehead renderas="sect4" id="algorithm_with_properties_pick_next_bridgehead">
  2859. <phrase id="algorithm_with_properties_pick_next"/>
  2860. <link linkend="algorithm_with_properties_pick_next">Member
  2861. function <code>pick_next</code>()</link>
  2862. </bridgehead>
  2863. </para>
  2864. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2865. </programlisting>
  2866. <variablelist>
  2867. <title></title>
  2868. <varlistentry>
  2869. <term>Returns:</term>
  2870. <listitem>
  2871. <para>
  2872. the fiber which is to be resumed next, or <code><phrase role="keyword">nullptr</phrase></code>
  2873. if there is no ready fiber.
  2874. </para>
  2875. </listitem>
  2876. </varlistentry>
  2877. <varlistentry>
  2878. <term>Throws:</term>
  2879. <listitem>
  2880. <para>
  2881. Nothing.
  2882. </para>
  2883. </listitem>
  2884. </varlistentry>
  2885. <varlistentry>
  2886. <term>Note:</term>
  2887. <listitem>
  2888. <para>
  2889. same as <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>
  2890. </para>
  2891. </listitem>
  2892. </varlistentry>
  2893. </variablelist>
  2894. <para>
  2895. <bridgehead renderas="sect4" id="algorithm_with_properties_has_ready_fibers_bridgehead">
  2896. <phrase id="algorithm_with_properties_has_ready_fibers"/>
  2897. <link linkend="algorithm_with_properties_has_ready_fibers">Member
  2898. function <code>has_ready_fibers</code>()</link>
  2899. </bridgehead>
  2900. </para>
  2901. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2902. </programlisting>
  2903. <variablelist>
  2904. <title></title>
  2905. <varlistentry>
  2906. <term>Returns:</term>
  2907. <listitem>
  2908. <para>
  2909. <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
  2910. ready to run.
  2911. </para>
  2912. </listitem>
  2913. </varlistentry>
  2914. <varlistentry>
  2915. <term>Throws:</term>
  2916. <listitem>
  2917. <para>
  2918. Nothing.
  2919. </para>
  2920. </listitem>
  2921. </varlistentry>
  2922. <varlistentry>
  2923. <term>Note:</term>
  2924. <listitem>
  2925. <para>
  2926. same as <link linkend="algorithm_has_ready_fibers"><code>algorithm::has_ready_fibers()</code></link>
  2927. </para>
  2928. </listitem>
  2929. </varlistentry>
  2930. </variablelist>
  2931. <para>
  2932. <bridgehead renderas="sect4" id="algorithm_with_properties_suspend_until_bridgehead">
  2933. <phrase id="algorithm_with_properties_suspend_until"/>
  2934. <link linkend="algorithm_with_properties_suspend_until">Member
  2935. function <code>suspend_until</code>()</link>
  2936. </bridgehead>
  2937. </para>
  2938. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  2939. </programlisting>
  2940. <variablelist>
  2941. <title></title>
  2942. <varlistentry>
  2943. <term>Effects:</term>
  2944. <listitem>
  2945. <para>
  2946. Informs the scheduler that no fiber will be ready until time-point <code><phrase
  2947. role="identifier">abs_time</phrase></code>.
  2948. </para>
  2949. </listitem>
  2950. </varlistentry>
  2951. <varlistentry>
  2952. <term>Note:</term>
  2953. <listitem>
  2954. <para>
  2955. same as <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>
  2956. </para>
  2957. </listitem>
  2958. </varlistentry>
  2959. </variablelist>
  2960. <para>
  2961. <bridgehead renderas="sect4" id="algorithm_with_properties_notify_bridgehead">
  2962. <phrase id="algorithm_with_properties_notify"/>
  2963. <link linkend="algorithm_with_properties_notify">Member
  2964. function <code>notify</code>()</link>
  2965. </bridgehead>
  2966. </para>
  2967. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  2968. </programlisting>
  2969. <variablelist>
  2970. <title></title>
  2971. <varlistentry>
  2972. <term>Effects:</term>
  2973. <listitem>
  2974. <para>
  2975. Requests the scheduler to return from a pending call to <link linkend="algorithm_with_properties_suspend_until"><code>algorithm_with_properties::suspend_until()</code></link>.
  2976. </para>
  2977. </listitem>
  2978. </varlistentry>
  2979. <varlistentry>
  2980. <term>Note:</term>
  2981. <listitem>
  2982. <para>
  2983. same as <link linkend="algorithm_notify"><code>algorithm::notify()</code></link>
  2984. </para>
  2985. </listitem>
  2986. </varlistentry>
  2987. </variablelist>
  2988. <para>
  2989. <bridgehead renderas="sect4" id="algorithm_with_properties_properties_bridgehead">
  2990. <phrase id="algorithm_with_properties_properties"/>
  2991. <link linkend="algorithm_with_properties_properties">Member
  2992. function <code>properties</code>()</link>
  2993. </bridgehead>
  2994. </para>
  2995. <programlisting><phrase role="identifier">PROPS</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  2996. </programlisting>
  2997. <variablelist>
  2998. <title></title>
  2999. <varlistentry>
  3000. <term>Returns:</term>
  3001. <listitem>
  3002. <para>
  3003. the <code><phrase role="identifier">PROPS</phrase></code> instance associated
  3004. with fiber <code><phrase role="identifier">f</phrase></code>.
  3005. </para>
  3006. </listitem>
  3007. </varlistentry>
  3008. <varlistentry>
  3009. <term>Throws:</term>
  3010. <listitem>
  3011. <para>
  3012. Nothing.
  3013. </para>
  3014. </listitem>
  3015. </varlistentry>
  3016. <varlistentry>
  3017. <term>Note:</term>
  3018. <listitem>
  3019. <para>
  3020. The fiber&#8217;s associated <code><phrase role="identifier">PROPS</phrase></code>
  3021. instance is already passed to <link linkend="algorithm_with_properties_awakened"><code>algorithm_with_properties::awakened()</code></link> and
  3022. <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link>.
  3023. However, every <link linkend="class_algorithm"><code>algorithm</code></link> subclass is expected to track
  3024. a collection of ready <link linkend="class_context"><code>context</code></link> instances. This method allows
  3025. your custom scheduler to retrieve the <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass
  3026. instance for any <code><phrase role="identifier">context</phrase></code>
  3027. in its collection.
  3028. </para>
  3029. </listitem>
  3030. </varlistentry>
  3031. </variablelist>
  3032. <para>
  3033. <bridgehead renderas="sect4" id="algorithm_with_properties_property_change_bridgehead">
  3034. <phrase id="algorithm_with_properties_property_change"/>
  3035. <link linkend="algorithm_with_properties_property_change">Member
  3036. function <code>property_change</code>()</link>
  3037. </bridgehead>
  3038. </para>
  3039. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">property_change</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">,</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3040. </programlisting>
  3041. <variablelist>
  3042. <title></title>
  3043. <varlistentry>
  3044. <term>Effects:</term>
  3045. <listitem>
  3046. <para>
  3047. Notify the custom scheduler of a possibly-relevant change to a property
  3048. belonging to fiber <code><phrase role="identifier">f</phrase></code>.
  3049. <code><phrase role="identifier">properties</phrase></code> contains the
  3050. new values of all relevant properties.
  3051. </para>
  3052. </listitem>
  3053. </varlistentry>
  3054. <varlistentry>
  3055. <term>Throws:</term>
  3056. <listitem>
  3057. <para>
  3058. Nothing.
  3059. </para>
  3060. </listitem>
  3061. </varlistentry>
  3062. <varlistentry>
  3063. <term>Note:</term>
  3064. <listitem>
  3065. <para>
  3066. This method is only called when a custom <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass
  3067. explicitly calls <link linkend="fiber_properties_notify"><code>fiber_properties::notify()</code></link>.
  3068. </para>
  3069. </listitem>
  3070. </varlistentry>
  3071. </variablelist>
  3072. <para>
  3073. <bridgehead renderas="sect4" id="algorithm_with_properties_new_properties_bridgehead">
  3074. <phrase id="algorithm_with_properties_new_properties"/>
  3075. <link linkend="algorithm_with_properties_new_properties">Member
  3076. function <code>new_properties</code>()</link>
  3077. </bridgehead>
  3078. </para>
  3079. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">fiber_properties</phrase> <phrase role="special">*</phrase> <phrase role="identifier">new_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">);</phrase>
  3080. </programlisting>
  3081. <variablelist>
  3082. <title></title>
  3083. <varlistentry>
  3084. <term>Returns:</term>
  3085. <listitem>
  3086. <para>
  3087. A new instance of <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass <code><phrase
  3088. role="identifier">PROPS</phrase></code>.
  3089. </para>
  3090. </listitem>
  3091. </varlistentry>
  3092. <varlistentry>
  3093. <term>Note:</term>
  3094. <listitem>
  3095. <para>
  3096. By default, <code><phrase role="identifier">algorithm_with_properties</phrase><phrase
  3097. role="special">&lt;&gt;::</phrase><phrase role="identifier">new_properties</phrase><phrase
  3098. role="special">()</phrase></code> simply returns <code><phrase role="keyword">new</phrase>
  3099. <phrase role="identifier">PROPS</phrase><phrase role="special">(</phrase><phrase
  3100. role="identifier">f</phrase><phrase role="special">)</phrase></code>,
  3101. placing the <code><phrase role="identifier">PROPS</phrase></code> instance
  3102. on the heap. Override this method to allocate <code><phrase role="identifier">PROPS</phrase></code>
  3103. some other way. The returned <code><phrase role="identifier">fiber_properties</phrase></code>
  3104. pointer must point to the <code><phrase role="identifier">PROPS</phrase></code>
  3105. instance to be associated with fiber <code><phrase role="identifier">f</phrase></code>.
  3106. </para>
  3107. </listitem>
  3108. </varlistentry>
  3109. </variablelist>
  3110. <para>
  3111. <anchor id="context"/><bridgehead renderas="sect4" id="class_context_bridgehead">
  3112. <phrase id="class_context"/>
  3113. <link linkend="class_context">Class
  3114. <code>context</code></link>
  3115. </bridgehead>
  3116. </para>
  3117. <para>
  3118. While you are free to treat <code><phrase role="identifier">context</phrase><phrase
  3119. role="special">*</phrase></code> as an opaque token, certain <code><phrase
  3120. role="identifier">context</phrase></code> members may be useful to a custom
  3121. scheduler implementation.
  3122. </para>
  3123. <para>
  3124. <anchor id="ready_queue_t"/>Of particular note is the fact that <code><phrase
  3125. role="identifier">context</phrase></code> contains a hook to participate in
  3126. a <ulink url="http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html"><code><phrase
  3127. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">intrusive</phrase><phrase
  3128. role="special">::</phrase><phrase role="identifier">list</phrase></code></ulink>
  3129. <literal>typedef</literal>&#8217;ed as <code><phrase role="identifier">boost</phrase><phrase
  3130. role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
  3131. role="special">::</phrase><phrase role="identifier">scheduler</phrase><phrase
  3132. role="special">::</phrase><phrase role="identifier">ready_queue_t</phrase></code>.
  3133. This hook is reserved for use by <link linkend="class_algorithm"><code>algorithm</code></link> implementations. (For
  3134. instance, <link linkend="class_round_robin"><code>round_robin</code></link> contains a <code><phrase role="identifier">ready_queue_t</phrase></code>
  3135. instance to manage its ready fibers.) See <link linkend="context_ready_is_linked"><code>context::ready_is_linked()</code></link>,
  3136. <link linkend="context_ready_link"><code>context::ready_link()</code></link>, <link linkend="context_ready_unlink"><code>context::ready_unlink()</code></link>.
  3137. </para>
  3138. <para>
  3139. Your <code><phrase role="identifier">algorithm</phrase></code> implementation
  3140. may use any container you desire to manage passed <code><phrase role="identifier">context</phrase></code>
  3141. instances. <code><phrase role="identifier">ready_queue_t</phrase></code> avoids
  3142. some of the overhead of typical STL containers.
  3143. </para>
  3144. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  3145. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  3146. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  3147. <phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">type</phrase> <phrase role="special">{</phrase>
  3148. <phrase role="identifier">none</phrase> <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase>
  3149. <phrase role="identifier">main_context</phrase> <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase> <phrase role="comment">// fiber associated with thread's stack</phrase>
  3150. <phrase role="identifier">dispatcher_context</phrase> <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase> <phrase role="comment">// special fiber for maintenance operations</phrase>
  3151. <phrase role="identifier">worker_context</phrase> <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase> <phrase role="comment">// fiber not special to the library</phrase>
  3152. <phrase role="identifier">pinned_context</phrase> <phrase role="special">=</phrase> <emphasis>unspecified</emphasis> <phrase role="comment">// fiber must not be migrated to another thread</phrase>
  3153. <phrase role="special">};</phrase>
  3154. <phrase role="keyword">class</phrase> <phrase role="identifier">context</phrase> <phrase role="special">{</phrase>
  3155. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  3156. <phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
  3157. <phrase role="keyword">static</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">active</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3158. <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  3159. <phrase role="identifier">context</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  3160. <phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3161. <phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3162. <phrase role="keyword">void</phrase> <phrase role="identifier">attach</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3163. <phrase role="keyword">bool</phrase> <phrase role="identifier">is_context</phrase><phrase role="special">(</phrase> <phrase role="identifier">type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3164. <phrase role="keyword">bool</phrase> <phrase role="identifier">is_terminated</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3165. <phrase role="keyword">bool</phrase> <phrase role="identifier">ready_is_linked</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3166. <phrase role="keyword">bool</phrase> <phrase role="identifier">remote_ready_is_linked</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3167. <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_is_linked</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3168. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&gt;</phrase>
  3169. <phrase role="keyword">void</phrase> <phrase role="identifier">ready_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3170. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&gt;</phrase>
  3171. <phrase role="keyword">void</phrase> <phrase role="identifier">remote_ready_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3172. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&gt;</phrase>
  3173. <phrase role="keyword">void</phrase> <phrase role="identifier">wait_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3174. <phrase role="keyword">void</phrase> <phrase role="identifier">ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3175. <phrase role="keyword">void</phrase> <phrase role="identifier">remote_ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3176. <phrase role="keyword">void</phrase> <phrase role="identifier">wait_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3177. <phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3178. <phrase role="keyword">void</phrase> <phrase role="identifier">schedule</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3179. <phrase role="special">};</phrase>
  3180. <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3181. <phrase role="special">}}</phrase>
  3182. </programlisting>
  3183. <para>
  3184. <bridgehead renderas="sect4" id="context_active_bridgehead">
  3185. <phrase id="context_active"/>
  3186. <link linkend="context_active">Static member function
  3187. <code>active</code>()</link>
  3188. </bridgehead>
  3189. </para>
  3190. <programlisting><phrase role="keyword">static</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">active</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3191. </programlisting>
  3192. <variablelist>
  3193. <title></title>
  3194. <varlistentry>
  3195. <term>Returns:</term>
  3196. <listitem>
  3197. <para>
  3198. Pointer to instance of current fiber.
  3199. </para>
  3200. </listitem>
  3201. </varlistentry>
  3202. <varlistentry>
  3203. <term>Throws:</term>
  3204. <listitem>
  3205. <para>
  3206. Nothing
  3207. </para>
  3208. </listitem>
  3209. </varlistentry>
  3210. </variablelist>
  3211. <para>
  3212. <bridgehead renderas="sect4" id="context_get_id_bridgehead">
  3213. <phrase id="context_get_id"/>
  3214. <link linkend="context_get_id">Member function <code>get_id</code>()</link>
  3215. </bridgehead>
  3216. </para>
  3217. <programlisting><phrase role="identifier">context</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3218. </programlisting>
  3219. <variablelist>
  3220. <title></title>
  3221. <varlistentry>
  3222. <term>Returns:</term>
  3223. <listitem>
  3224. <para>
  3225. If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  3226. refers to a fiber of execution, an instance of <link linkend="class_fiber_id"><code><phrase
  3227. role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
  3228. role="identifier">id</phrase></code></link> that represents that fiber. Otherwise
  3229. returns a default-constructed <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
  3230. role="special">::</phrase><phrase role="identifier">id</phrase></code></link>.
  3231. </para>
  3232. </listitem>
  3233. </varlistentry>
  3234. <varlistentry>
  3235. <term>Throws:</term>
  3236. <listitem>
  3237. <para>
  3238. Nothing
  3239. </para>
  3240. </listitem>
  3241. </varlistentry>
  3242. <varlistentry>
  3243. <term>See also:</term>
  3244. <listitem>
  3245. <para>
  3246. <link linkend="fiber_get_id"><code>fiber::get_id()</code></link>
  3247. </para>
  3248. </listitem>
  3249. </varlistentry>
  3250. </variablelist>
  3251. <para>
  3252. <bridgehead renderas="sect4" id="context_attach_bridgehead">
  3253. <phrase id="context_attach"/>
  3254. <link linkend="context_attach">Member function <code>attach</code>()</link>
  3255. </bridgehead>
  3256. </para>
  3257. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">attach</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3258. </programlisting>
  3259. <variablelist>
  3260. <title></title>
  3261. <varlistentry>
  3262. <term>Precondition:</term>
  3263. <listitem>
  3264. <para>
  3265. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  3266. role="identifier">get_scheduler</phrase><phrase role="special">()</phrase>
  3267. <phrase role="special">==</phrase> <phrase role="keyword">nullptr</phrase></code>
  3268. </para>
  3269. </listitem>
  3270. </varlistentry>
  3271. <varlistentry>
  3272. <term>Effects:</term>
  3273. <listitem>
  3274. <para>
  3275. Attach fiber <code><phrase role="identifier">f</phrase></code> to scheduler
  3276. running <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
  3277. </para>
  3278. </listitem>
  3279. </varlistentry>
  3280. <varlistentry>
  3281. <term>Postcondition:</term>
  3282. <listitem>
  3283. <para>
  3284. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  3285. role="identifier">get_scheduler</phrase><phrase role="special">()</phrase>
  3286. <phrase role="special">!=</phrase> <phrase role="keyword">nullptr</phrase></code>
  3287. </para>
  3288. </listitem>
  3289. </varlistentry>
  3290. <varlistentry>
  3291. <term>Throws:</term>
  3292. <listitem>
  3293. <para>
  3294. Nothing
  3295. </para>
  3296. </listitem>
  3297. </varlistentry>
  3298. <varlistentry>
  3299. <term>Note:</term>
  3300. <listitem>
  3301. <para>
  3302. A typical call: <code><phrase role="identifier">boost</phrase><phrase
  3303. role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
  3304. role="special">::</phrase><phrase role="identifier">context</phrase><phrase
  3305. role="special">::</phrase><phrase role="identifier">active</phrase><phrase
  3306. role="special">()-&gt;</phrase><phrase role="identifier">attach</phrase><phrase
  3307. role="special">(</phrase><phrase role="identifier">f</phrase><phrase
  3308. role="special">);</phrase></code>
  3309. </para>
  3310. </listitem>
  3311. </varlistentry>
  3312. <varlistentry>
  3313. <term>Note:</term>
  3314. <listitem>
  3315. <para>
  3316. <code><phrase role="identifier">f</phrase></code> must not be the running
  3317. fiber&#8217;s context. It must not be <link linkend="blocking"><emphasis>blocked</emphasis></link>
  3318. or terminated. It must not be a <code><phrase role="identifier">pinned_context</phrase></code>.
  3319. It must be currently detached. It must not currently be linked into an
  3320. <link linkend="class_algorithm"><code>algorithm</code></link> implementation&#8217;s ready queue. Most of these conditions
  3321. are implied by <code><phrase role="identifier">f</phrase></code> being
  3322. owned by an <code><phrase role="identifier">algorithm</phrase></code>
  3323. implementation: that is, it has been passed to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> but
  3324. has not yet been returned by <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>.
  3325. Typically a <code><phrase role="identifier">pick_next</phrase><phrase
  3326. role="special">()</phrase></code> implementation would call <code><phrase
  3327. role="identifier">attach</phrase><phrase role="special">()</phrase></code>
  3328. with the <code><phrase role="identifier">context</phrase><phrase role="special">*</phrase></code>
  3329. it is about to return. It must first remove <code><phrase role="identifier">f</phrase></code>
  3330. from its ready queue. You should never pass a <code><phrase role="identifier">pinned_context</phrase></code>
  3331. to <code><phrase role="identifier">attach</phrase><phrase role="special">()</phrase></code>
  3332. because you should never have called its <code><phrase role="identifier">detach</phrase><phrase
  3333. role="special">()</phrase></code> method in the first place.
  3334. </para>
  3335. </listitem>
  3336. </varlistentry>
  3337. </variablelist>
  3338. <para>
  3339. <bridgehead renderas="sect4" id="context_detach_bridgehead">
  3340. <phrase id="context_detach"/>
  3341. <link linkend="context_detach">Member function <code>detach</code>()</link>
  3342. </bridgehead>
  3343. </para>
  3344. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3345. </programlisting>
  3346. <variablelist>
  3347. <title></title>
  3348. <varlistentry>
  3349. <term>Precondition:</term>
  3350. <listitem>
  3351. <para>
  3352. <code><phrase role="special">(</phrase><phrase role="keyword">this</phrase><phrase
  3353. role="special">-&gt;</phrase><phrase role="identifier">get_scheduler</phrase><phrase
  3354. role="special">()</phrase> <phrase role="special">!=</phrase> <phrase
  3355. role="keyword">nullptr</phrase><phrase role="special">)</phrase> <phrase
  3356. role="special">&amp;&amp;</phrase> <phrase role="special">!</phrase>
  3357. <phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  3358. role="identifier">is_context</phrase><phrase role="special">(</phrase><phrase
  3359. role="identifier">pinned_context</phrase><phrase role="special">)</phrase></code>
  3360. </para>
  3361. </listitem>
  3362. </varlistentry>
  3363. <varlistentry>
  3364. <term>Effects:</term>
  3365. <listitem>
  3366. <para>
  3367. Detach fiber <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  3368. from its scheduler running <code><phrase role="special">*</phrase><phrase
  3369. role="keyword">this</phrase></code>.
  3370. </para>
  3371. </listitem>
  3372. </varlistentry>
  3373. <varlistentry>
  3374. <term>Throws:</term>
  3375. <listitem>
  3376. <para>
  3377. Nothing
  3378. </para>
  3379. </listitem>
  3380. </varlistentry>
  3381. <varlistentry>
  3382. <term>Postcondition:</term>
  3383. <listitem>
  3384. <para>
  3385. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  3386. role="identifier">get_scheduler</phrase><phrase role="special">()</phrase>
  3387. <phrase role="special">==</phrase> <phrase role="keyword">nullptr</phrase></code>
  3388. </para>
  3389. </listitem>
  3390. </varlistentry>
  3391. <varlistentry>
  3392. <term>Note:</term>
  3393. <listitem>
  3394. <para>
  3395. This method must be called on the thread with which the fiber is currently
  3396. associated. <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  3397. must not be the running fiber&#8217;s context. It must not be <link linkend="blocking"><emphasis>blocked</emphasis></link>
  3398. or terminated. It must not be a <code><phrase role="identifier">pinned_context</phrase></code>.
  3399. It must not be detached already. It must not already be linked into an
  3400. <link linkend="class_algorithm"><code>algorithm</code></link> implementation&#8217;s ready queue. Most of these conditions
  3401. are implied by <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  3402. being passed to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>; an <code><phrase
  3403. role="identifier">awakened</phrase><phrase role="special">()</phrase></code>
  3404. implementation must, however, test for <code><phrase role="identifier">pinned_context</phrase></code>.
  3405. It must call <code><phrase role="identifier">detach</phrase><phrase role="special">()</phrase></code>
  3406. <emphasis>before</emphasis> linking <code><phrase role="special">*</phrase><phrase
  3407. role="keyword">this</phrase></code> into its ready queue.
  3408. </para>
  3409. </listitem>
  3410. </varlistentry>
  3411. <varlistentry>
  3412. <term>Note:</term>
  3413. <listitem>
  3414. <para>
  3415. In particular, it is erroneous to attempt to migrate a fiber from one
  3416. thread to another by calling both <code><phrase role="identifier">detach</phrase><phrase
  3417. role="special">()</phrase></code> and <code><phrase role="identifier">attach</phrase><phrase
  3418. role="special">()</phrase></code> in the <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link> method.
  3419. <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>
  3420. is called on the intended destination thread. <code><phrase role="identifier">detach</phrase><phrase
  3421. role="special">()</phrase></code> must be called on the fiber&#8217;s original
  3422. thread. You must call <code><phrase role="identifier">detach</phrase><phrase
  3423. role="special">()</phrase></code> in the corresponding <code><phrase
  3424. role="identifier">awakened</phrase><phrase role="special">()</phrase></code>
  3425. method.
  3426. </para>
  3427. </listitem>
  3428. </varlistentry>
  3429. <varlistentry>
  3430. <term>Note:</term>
  3431. <listitem>
  3432. <para>
  3433. Unless you intend make a fiber available for potential migration to a
  3434. different thread, you should call neither <code><phrase role="identifier">detach</phrase><phrase
  3435. role="special">()</phrase></code> nor <code><phrase role="identifier">attach</phrase><phrase
  3436. role="special">()</phrase></code> with its <code><phrase role="identifier">context</phrase></code>.
  3437. </para>
  3438. </listitem>
  3439. </varlistentry>
  3440. </variablelist>
  3441. <para>
  3442. <bridgehead renderas="sect4" id="context_is_context_bridgehead">
  3443. <phrase id="context_is_context"/>
  3444. <link linkend="context_is_context">Member function
  3445. <code>is_context</code>()</link>
  3446. </bridgehead>
  3447. </para>
  3448. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">is_context</phrase><phrase role="special">(</phrase> <phrase role="identifier">type</phrase> <phrase role="identifier">t</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3449. </programlisting>
  3450. <variablelist>
  3451. <title></title>
  3452. <varlistentry>
  3453. <term>Returns:</term>
  3454. <listitem>
  3455. <para>
  3456. <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
  3457. role="keyword">this</phrase></code> is of the specified type.
  3458. </para>
  3459. </listitem>
  3460. </varlistentry>
  3461. <varlistentry>
  3462. <term>Throws:</term>
  3463. <listitem>
  3464. <para>
  3465. Nothing
  3466. </para>
  3467. </listitem>
  3468. </varlistentry>
  3469. <varlistentry>
  3470. <term>Note:</term>
  3471. <listitem>
  3472. <para>
  3473. <code><phrase role="identifier">type</phrase><phrase role="special">::</phrase><phrase
  3474. role="identifier">worker_context</phrase></code> here means any fiber
  3475. not special to the library. For <code><phrase role="identifier">type</phrase><phrase
  3476. role="special">::</phrase><phrase role="identifier">main_context</phrase></code>
  3477. the <code><phrase role="identifier">context</phrase></code> is associated
  3478. with the <quote>main</quote> fiber of the thread: the one implicitly
  3479. created by the thread itself, rather than one explicitly created by
  3480. <emphasis role="bold">Boost.Fiber</emphasis>. For <code><phrase role="identifier">type</phrase><phrase
  3481. role="special">::</phrase><phrase role="identifier">dispatcher_context</phrase></code>
  3482. the <code><phrase role="identifier">context</phrase></code> is associated
  3483. with a <quote>dispatching</quote> fiber, responsible for dispatching
  3484. awakened fibers to a scheduler&#8217;s ready-queue. The <quote>dispatching</quote>
  3485. fiber is an implementation detail of the fiber manager. The context of
  3486. the <quote>main</quote> or <quote>dispatching</quote> fiber &mdash; any fiber
  3487. for which <code><phrase role="identifier">is_context</phrase><phrase
  3488. role="special">(</phrase><phrase role="identifier">pinned_context</phrase><phrase
  3489. role="special">)</phrase></code> is <code><phrase role="keyword">true</phrase></code>
  3490. &mdash; must never be passed to <link linkend="context_detach"><code>context::detach()</code></link>.
  3491. </para>
  3492. </listitem>
  3493. </varlistentry>
  3494. </variablelist>
  3495. <para>
  3496. <bridgehead renderas="sect4" id="context_is_terminated_bridgehead">
  3497. <phrase id="context_is_terminated"/>
  3498. <link linkend="context_is_terminated">Member
  3499. function <code>is_terminated</code>()</link>
  3500. </bridgehead>
  3501. </para>
  3502. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">is_terminated</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3503. </programlisting>
  3504. <variablelist>
  3505. <title></title>
  3506. <varlistentry>
  3507. <term>Returns:</term>
  3508. <listitem>
  3509. <para>
  3510. <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
  3511. role="keyword">this</phrase></code> is no longer a valid context.
  3512. </para>
  3513. </listitem>
  3514. </varlistentry>
  3515. <varlistentry>
  3516. <term>Throws:</term>
  3517. <listitem>
  3518. <para>
  3519. Nothing
  3520. </para>
  3521. </listitem>
  3522. </varlistentry>
  3523. <varlistentry>
  3524. <term>Note:</term>
  3525. <listitem>
  3526. <para>
  3527. The <code><phrase role="identifier">context</phrase></code> has returned
  3528. from its fiber-function and is no longer considered a valid context.
  3529. </para>
  3530. </listitem>
  3531. </varlistentry>
  3532. </variablelist>
  3533. <para>
  3534. <bridgehead renderas="sect4" id="context_ready_is_linked_bridgehead">
  3535. <phrase id="context_ready_is_linked"/>
  3536. <link linkend="context_ready_is_linked">Member
  3537. function <code>ready_is_linked</code>()</link>
  3538. </bridgehead>
  3539. </para>
  3540. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">ready_is_linked</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3541. </programlisting>
  3542. <variablelist>
  3543. <title></title>
  3544. <varlistentry>
  3545. <term>Returns:</term>
  3546. <listitem>
  3547. <para>
  3548. <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
  3549. role="keyword">this</phrase></code> is stored in an <link linkend="class_algorithm"><code>algorithm</code></link>
  3550. implementation&#8217;s
  3551. ready-queue.
  3552. </para>
  3553. </listitem>
  3554. </varlistentry>
  3555. <varlistentry>
  3556. <term>Throws:</term>
  3557. <listitem>
  3558. <para>
  3559. Nothing
  3560. </para>
  3561. </listitem>
  3562. </varlistentry>
  3563. <varlistentry>
  3564. <term>Note:</term>
  3565. <listitem>
  3566. <para>
  3567. Specifically, this method indicates whether <link linkend="context_ready_link"><code>context::ready_link()</code></link> has
  3568. been called on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
  3569. <code><phrase role="identifier">ready_is_linked</phrase><phrase role="special">()</phrase></code>
  3570. has no information about participation in any other containers.
  3571. </para>
  3572. </listitem>
  3573. </varlistentry>
  3574. </variablelist>
  3575. <para>
  3576. <bridgehead renderas="sect4" id="context_remote_ready_is_linked_bridgehead">
  3577. <phrase id="context_remote_ready_is_linked"/>
  3578. <link linkend="context_remote_ready_is_linked">Member
  3579. function <code>remote_ready_is_linked</code>()</link>
  3580. </bridgehead>
  3581. </para>
  3582. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">remote_ready_is_linked</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3583. </programlisting>
  3584. <variablelist>
  3585. <title></title>
  3586. <varlistentry>
  3587. <term>Returns:</term>
  3588. <listitem>
  3589. <para>
  3590. <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
  3591. role="keyword">this</phrase></code> is stored in the fiber manager&#8217;s remote-ready-queue.
  3592. </para>
  3593. </listitem>
  3594. </varlistentry>
  3595. <varlistentry>
  3596. <term>Throws:</term>
  3597. <listitem>
  3598. <para>
  3599. Nothing
  3600. </para>
  3601. </listitem>
  3602. </varlistentry>
  3603. <varlistentry>
  3604. <term>Note:</term>
  3605. <listitem>
  3606. <para>
  3607. A <code><phrase role="identifier">context</phrase></code> signaled as
  3608. ready by another thread is first stored in the fiber manager&#8217;s remote-ready-queue.
  3609. This is the mechanism by which the fiber manager protects an <link linkend="class_algorithm"><code>algorithm</code></link> implementation
  3610. from cross-thread <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> calls.
  3611. </para>
  3612. </listitem>
  3613. </varlistentry>
  3614. </variablelist>
  3615. <para>
  3616. <bridgehead renderas="sect4" id="context_wait_is_linked_bridgehead">
  3617. <phrase id="context_wait_is_linked"/>
  3618. <link linkend="context_wait_is_linked">Member
  3619. function <code>wait_is_linked</code>()</link>
  3620. </bridgehead>
  3621. </para>
  3622. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">wait_is_linked</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3623. </programlisting>
  3624. <variablelist>
  3625. <title></title>
  3626. <varlistentry>
  3627. <term>Returns:</term>
  3628. <listitem>
  3629. <para>
  3630. <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
  3631. role="keyword">this</phrase></code> is stored in the wait-queue of some
  3632. synchronization object.
  3633. </para>
  3634. </listitem>
  3635. </varlistentry>
  3636. <varlistentry>
  3637. <term>Throws:</term>
  3638. <listitem>
  3639. <para>
  3640. Nothing
  3641. </para>
  3642. </listitem>
  3643. </varlistentry>
  3644. <varlistentry>
  3645. <term>Note:</term>
  3646. <listitem>
  3647. <para>
  3648. The <code><phrase role="identifier">context</phrase></code> of a fiber
  3649. waiting on a synchronization object (e.g. <code><phrase role="identifier">mutex</phrase></code>,
  3650. <code><phrase role="identifier">condition_variable</phrase></code> etc.)
  3651. is stored in the wait-queue of that synchronization object.
  3652. </para>
  3653. </listitem>
  3654. </varlistentry>
  3655. </variablelist>
  3656. <para>
  3657. <bridgehead renderas="sect4" id="context_ready_link_bridgehead">
  3658. <phrase id="context_ready_link"/>
  3659. <link linkend="context_ready_link">Member function
  3660. <code>ready_link</code>()</link>
  3661. </bridgehead>
  3662. </para>
  3663. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&gt;</phrase>
  3664. <phrase role="keyword">void</phrase> <phrase role="identifier">ready_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lst</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3665. </programlisting>
  3666. <variablelist>
  3667. <title></title>
  3668. <varlistentry>
  3669. <term>Effects:</term>
  3670. <listitem>
  3671. <para>
  3672. Stores <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  3673. in ready-queue <code><phrase role="identifier">lst</phrase></code>.
  3674. </para>
  3675. </listitem>
  3676. </varlistentry>
  3677. <varlistentry>
  3678. <term>Throws:</term>
  3679. <listitem>
  3680. <para>
  3681. Nothing
  3682. </para>
  3683. </listitem>
  3684. </varlistentry>
  3685. <varlistentry>
  3686. <term>Note:</term>
  3687. <listitem>
  3688. <para>
  3689. Argument <code><phrase role="identifier">lst</phrase></code> must be
  3690. a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>,
  3691. e.g. an instance of <code><phrase role="identifier">boost</phrase><phrase
  3692. role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
  3693. role="special">::</phrase><phrase role="identifier">scheduler</phrase><phrase
  3694. role="special">::</phrase><phrase role="identifier">ready_queue_t</phrase></code>.
  3695. Specifically, it must be a <ulink url="http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html"><code><phrase
  3696. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  3697. role="identifier">intrusive</phrase><phrase role="special">::</phrase><phrase
  3698. role="identifier">list</phrase></code></ulink> compatible with the <code><phrase
  3699. role="identifier">list_member_hook</phrase></code> stored in the <code><phrase
  3700. role="identifier">context</phrase></code> object.
  3701. </para>
  3702. </listitem>
  3703. </varlistentry>
  3704. </variablelist>
  3705. <para>
  3706. <bridgehead renderas="sect4" id="context_remote_ready_link_bridgehead">
  3707. <phrase id="context_remote_ready_link"/>
  3708. <link linkend="context_remote_ready_link">Member
  3709. function <code>remote_ready_link</code>()</link>
  3710. </bridgehead>
  3711. </para>
  3712. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&gt;</phrase>
  3713. <phrase role="keyword">void</phrase> <phrase role="identifier">remote_ready_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lst</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3714. </programlisting>
  3715. <variablelist>
  3716. <title></title>
  3717. <varlistentry>
  3718. <term>Effects:</term>
  3719. <listitem>
  3720. <para>
  3721. Stores <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  3722. in remote-ready-queue <code><phrase role="identifier">lst</phrase></code>.
  3723. </para>
  3724. </listitem>
  3725. </varlistentry>
  3726. <varlistentry>
  3727. <term>Throws:</term>
  3728. <listitem>
  3729. <para>
  3730. Nothing
  3731. </para>
  3732. </listitem>
  3733. </varlistentry>
  3734. <varlistentry>
  3735. <term>Note:</term>
  3736. <listitem>
  3737. <para>
  3738. Argument <code><phrase role="identifier">lst</phrase></code> must be
  3739. a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>.
  3740. </para>
  3741. </listitem>
  3742. </varlistentry>
  3743. </variablelist>
  3744. <para>
  3745. <bridgehead renderas="sect4" id="context_wait_link_bridgehead">
  3746. <phrase id="context_wait_link"/>
  3747. <link linkend="context_wait_link">Member function
  3748. <code>wait_link</code>()</link>
  3749. </bridgehead>
  3750. </para>
  3751. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&gt;</phrase>
  3752. <phrase role="keyword">void</phrase> <phrase role="identifier">wait_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lst</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3753. </programlisting>
  3754. <variablelist>
  3755. <title></title>
  3756. <varlistentry>
  3757. <term>Effects:</term>
  3758. <listitem>
  3759. <para>
  3760. Stores <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  3761. in wait-queue <code><phrase role="identifier">lst</phrase></code>.
  3762. </para>
  3763. </listitem>
  3764. </varlistentry>
  3765. <varlistentry>
  3766. <term>Throws:</term>
  3767. <listitem>
  3768. <para>
  3769. Nothing
  3770. </para>
  3771. </listitem>
  3772. </varlistentry>
  3773. <varlistentry>
  3774. <term>Note:</term>
  3775. <listitem>
  3776. <para>
  3777. Argument <code><phrase role="identifier">lst</phrase></code> must be
  3778. a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>.
  3779. </para>
  3780. </listitem>
  3781. </varlistentry>
  3782. </variablelist>
  3783. <para>
  3784. <bridgehead renderas="sect4" id="context_ready_unlink_bridgehead">
  3785. <phrase id="context_ready_unlink"/>
  3786. <link linkend="context_ready_unlink">Member
  3787. function <code>ready_unlink</code>()</link>
  3788. </bridgehead>
  3789. </para>
  3790. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3791. </programlisting>
  3792. <variablelist>
  3793. <title></title>
  3794. <varlistentry>
  3795. <term>Effects:</term>
  3796. <listitem>
  3797. <para>
  3798. Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  3799. from ready-queue: undoes the effect of <link linkend="context_ready_link"><code>context::ready_link()</code></link>.
  3800. </para>
  3801. </listitem>
  3802. </varlistentry>
  3803. <varlistentry>
  3804. <term>Throws:</term>
  3805. <listitem>
  3806. <para>
  3807. Nothing
  3808. </para>
  3809. </listitem>
  3810. </varlistentry>
  3811. </variablelist>
  3812. <para>
  3813. <bridgehead renderas="sect4" id="context_remote_ready_unlink_bridgehead">
  3814. <phrase id="context_remote_ready_unlink"/>
  3815. <link linkend="context_remote_ready_unlink">Member
  3816. function <code>remote_ready_unlink</code>()</link>
  3817. </bridgehead>
  3818. </para>
  3819. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">remote_ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3820. </programlisting>
  3821. <variablelist>
  3822. <title></title>
  3823. <varlistentry>
  3824. <term>Effects:</term>
  3825. <listitem>
  3826. <para>
  3827. Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  3828. from remote-ready-queue.
  3829. </para>
  3830. </listitem>
  3831. </varlistentry>
  3832. <varlistentry>
  3833. <term>Throws:</term>
  3834. <listitem>
  3835. <para>
  3836. Nothing
  3837. </para>
  3838. </listitem>
  3839. </varlistentry>
  3840. </variablelist>
  3841. <para>
  3842. <bridgehead renderas="sect4" id="context_wait_unlink_bridgehead">
  3843. <phrase id="context_wait_unlink"/>
  3844. <link linkend="context_wait_unlink">Member
  3845. function <code>wait_unlink</code>()</link>
  3846. </bridgehead>
  3847. </para>
  3848. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3849. </programlisting>
  3850. <variablelist>
  3851. <title></title>
  3852. <varlistentry>
  3853. <term>Effects:</term>
  3854. <listitem>
  3855. <para>
  3856. Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  3857. from wait-queue.
  3858. </para>
  3859. </listitem>
  3860. </varlistentry>
  3861. <varlistentry>
  3862. <term>Throws:</term>
  3863. <listitem>
  3864. <para>
  3865. Nothing
  3866. </para>
  3867. </listitem>
  3868. </varlistentry>
  3869. </variablelist>
  3870. <para>
  3871. <bridgehead renderas="sect4" id="context_suspend_bridgehead">
  3872. <phrase id="context_suspend"/>
  3873. <link linkend="context_suspend">Member function <code>suspend</code>()</link>
  3874. </bridgehead>
  3875. </para>
  3876. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3877. </programlisting>
  3878. <variablelist>
  3879. <title></title>
  3880. <varlistentry>
  3881. <term>Effects:</term>
  3882. <listitem>
  3883. <para>
  3884. Suspends the running fiber (the fiber associated with <code><phrase role="special">*</phrase><phrase
  3885. role="keyword">this</phrase></code>) until some other fiber passes <code><phrase
  3886. role="keyword">this</phrase></code> to <link linkend="context_schedule"><code>context::schedule()</code></link>.
  3887. <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  3888. is marked as not-ready, and control passes to the scheduler to select
  3889. another fiber to run.
  3890. </para>
  3891. </listitem>
  3892. </varlistentry>
  3893. <varlistentry>
  3894. <term>Throws:</term>
  3895. <listitem>
  3896. <para>
  3897. Nothing
  3898. </para>
  3899. </listitem>
  3900. </varlistentry>
  3901. <varlistentry>
  3902. <term>Note:</term>
  3903. <listitem>
  3904. <para>
  3905. This is a low-level API potentially useful for integration with other
  3906. frameworks. It is not intended to be directly invoked by a typical application
  3907. program.
  3908. </para>
  3909. </listitem>
  3910. </varlistentry>
  3911. <varlistentry>
  3912. <term>Note:</term>
  3913. <listitem>
  3914. <para>
  3915. The burden is on the caller to arrange for a call to <code><phrase role="identifier">schedule</phrase><phrase
  3916. role="special">()</phrase></code> with a pointer to <code><phrase role="keyword">this</phrase></code>
  3917. at some future time.
  3918. </para>
  3919. </listitem>
  3920. </varlistentry>
  3921. </variablelist>
  3922. <para>
  3923. <bridgehead renderas="sect4" id="context_schedule_bridgehead">
  3924. <phrase id="context_schedule"/>
  3925. <link linkend="context_schedule">Member function
  3926. <code>schedule</code>()</link>
  3927. </bridgehead>
  3928. </para>
  3929. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">schedule</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase> <phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3930. </programlisting>
  3931. <variablelist>
  3932. <title></title>
  3933. <varlistentry>
  3934. <term>Effects:</term>
  3935. <listitem>
  3936. <para>
  3937. Mark the fiber associated with context <code><phrase role="special">*</phrase><phrase
  3938. role="identifier">ctx</phrase></code> as being ready to run. This does
  3939. not immediately resume that fiber; rather it passes the fiber to the
  3940. scheduler for subsequent resumption. If the scheduler is idle (has not
  3941. returned from a call to <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>),
  3942. <link linkend="algorithm_notify"><code>algorithm::notify()</code></link> is called to wake it up.
  3943. </para>
  3944. </listitem>
  3945. </varlistentry>
  3946. <varlistentry>
  3947. <term>Throws:</term>
  3948. <listitem>
  3949. <para>
  3950. Nothing
  3951. </para>
  3952. </listitem>
  3953. </varlistentry>
  3954. <varlistentry>
  3955. <term>Note:</term>
  3956. <listitem>
  3957. <para>
  3958. This is a low-level API potentially useful for integration with other
  3959. frameworks. It is not intended to be directly invoked by a typical application
  3960. program.
  3961. </para>
  3962. </listitem>
  3963. </varlistentry>
  3964. <varlistentry>
  3965. <term>Note:</term>
  3966. <listitem>
  3967. <para>
  3968. It is explicitly supported to call <code><phrase role="identifier">schedule</phrase><phrase
  3969. role="special">(</phrase><phrase role="identifier">ctx</phrase><phrase
  3970. role="special">)</phrase></code> from a thread other than the one on
  3971. which <code><phrase role="special">*</phrase><phrase role="identifier">ctx</phrase></code>
  3972. is currently suspended. The corresponding fiber will be resumed on its
  3973. original thread in due course.
  3974. </para>
  3975. </listitem>
  3976. </varlistentry>
  3977. </variablelist>
  3978. <para>
  3979. <bridgehead renderas="sect4" id="context_less_bridgehead">
  3980. <phrase id="context_less"/>
  3981. <link linkend="context_less">Non-member function <code>operator&lt;()</code></link>
  3982. </bridgehead>
  3983. </para>
  3984. <programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  3985. </programlisting>
  3986. <variablelist>
  3987. <title></title>
  3988. <varlistentry>
  3989. <term>Returns:</term>
  3990. <listitem>
  3991. <para>
  3992. <code><phrase role="keyword">true</phrase></code> if <code><phrase role="identifier">l</phrase><phrase
  3993. role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase
  3994. role="special">()</phrase> <phrase role="special">&lt;</phrase> <phrase
  3995. role="identifier">r</phrase><phrase role="special">.</phrase><phrase
  3996. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  3997. is <code><phrase role="keyword">true</phrase></code>, <code><phrase role="keyword">false</phrase></code>
  3998. otherwise.
  3999. </para>
  4000. </listitem>
  4001. </varlistentry>
  4002. <varlistentry>
  4003. <term>Throws:</term>
  4004. <listitem>
  4005. <para>
  4006. Nothing.
  4007. </para>
  4008. </listitem>
  4009. </varlistentry>
  4010. </variablelist>
  4011. </section>
  4012. <section id="fiber.stack">
  4013. <title><anchor id="stack"/><link linkend="fiber.stack">Stack allocation</link></title>
  4014. <para>
  4015. A <link linkend="class_fiber"><code>fiber</code></link> uses internally an __econtext__ which manages a set of registers
  4016. and a stack. The memory used by the stack is allocated/deallocated via a <emphasis>stack_allocator</emphasis>
  4017. which is required to model a <link linkend="stack_allocator_concept"><emphasis>stack-allocator
  4018. concept</emphasis></link>.
  4019. </para>
  4020. <para>
  4021. A <emphasis>stack_allocator</emphasis> can be passed to <link linkend="fiber_fiber"><code><phrase
  4022. role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase
  4023. role="special">()</phrase></code></link> or to <link linkend="fibers_async"><code>fibers::async()</code></link>.
  4024. </para>
  4025. <anchor id="stack_allocator_concept"/>
  4026. <bridgehead renderas="sect3" id="fiber.stack.h0">
  4027. <phrase id="fiber.stack.stack_allocator_concept"/><link linkend="fiber.stack.stack_allocator_concept">stack-allocator
  4028. concept</link>
  4029. </bridgehead>
  4030. <para>
  4031. A <emphasis>stack_allocator</emphasis> must satisfy the <emphasis>stack-allocator
  4032. concept</emphasis> requirements shown in the following table, in which <code><phrase
  4033. role="identifier">a</phrase></code> is an object of a <emphasis>stack_allocator</emphasis>
  4034. type, <code><phrase role="identifier">sctx</phrase></code> is a <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_context.html"><code><phrase
  4035. role="identifier">stack_context</phrase></code></ulink>, and <code><phrase
  4036. role="identifier">size</phrase></code> is a <code><phrase role="identifier">std</phrase><phrase
  4037. role="special">::</phrase><phrase role="identifier">size_t</phrase></code>:
  4038. </para>
  4039. <informaltable frame="all">
  4040. <tgroup cols="3">
  4041. <thead>
  4042. <row>
  4043. <entry>
  4044. <para>
  4045. expression
  4046. </para>
  4047. </entry>
  4048. <entry>
  4049. <para>
  4050. return type
  4051. </para>
  4052. </entry>
  4053. <entry>
  4054. <para>
  4055. notes
  4056. </para>
  4057. </entry>
  4058. </row>
  4059. </thead>
  4060. <tbody>
  4061. <row>
  4062. <entry>
  4063. <para>
  4064. <code><phrase role="identifier">a</phrase><phrase role="special">(</phrase><phrase
  4065. role="identifier">size</phrase><phrase role="special">)</phrase></code>
  4066. </para>
  4067. </entry>
  4068. <entry>
  4069. </entry>
  4070. <entry>
  4071. <para>
  4072. creates a stack allocator
  4073. </para>
  4074. </entry>
  4075. </row>
  4076. <row>
  4077. <entry>
  4078. <para>
  4079. <code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase
  4080. role="identifier">allocate</phrase><phrase role="special">()</phrase></code>
  4081. </para>
  4082. </entry>
  4083. <entry>
  4084. <para>
  4085. <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_context.html"><code><phrase
  4086. role="identifier">stack_context</phrase></code></ulink>
  4087. </para>
  4088. </entry>
  4089. <entry>
  4090. <para>
  4091. creates a stack
  4092. </para>
  4093. </entry>
  4094. </row>
  4095. <row>
  4096. <entry>
  4097. <para>
  4098. <code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase
  4099. role="identifier">deallocate</phrase><phrase role="special">(</phrase>
  4100. <phrase role="identifier">sctx</phrase><phrase role="special">)</phrase></code>
  4101. </para>
  4102. </entry>
  4103. <entry>
  4104. <para>
  4105. <code><phrase role="keyword">void</phrase></code>
  4106. </para>
  4107. </entry>
  4108. <entry>
  4109. <para>
  4110. deallocates the stack created by <code><phrase role="identifier">a</phrase><phrase
  4111. role="special">.</phrase><phrase role="identifier">allocate</phrase><phrase
  4112. role="special">()</phrase></code>
  4113. </para>
  4114. </entry>
  4115. </row>
  4116. </tbody>
  4117. </tgroup>
  4118. </informaltable>
  4119. <important>
  4120. <para>
  4121. The implementation of <code><phrase role="identifier">allocate</phrase><phrase
  4122. role="special">()</phrase></code> might include logic to protect against
  4123. exceeding the context's available stack size rather than leaving it as undefined
  4124. behaviour.
  4125. </para>
  4126. </important>
  4127. <important>
  4128. <para>
  4129. Calling <code><phrase role="identifier">deallocate</phrase><phrase role="special">()</phrase></code>
  4130. with a <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_context.html"><code><phrase
  4131. role="identifier">stack_context</phrase></code></ulink> not obtained from
  4132. <code><phrase role="identifier">allocate</phrase><phrase role="special">()</phrase></code>
  4133. results in undefined behaviour.
  4134. </para>
  4135. </important>
  4136. <note>
  4137. <para>
  4138. The memory for the stack is not required to be aligned; alignment takes place
  4139. inside __econtext__.
  4140. </para>
  4141. </note>
  4142. <para>
  4143. See also <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack.html">Boost.Context
  4144. stack allocation</ulink>. In particular, <code><phrase role="identifier">traits_type</phrase></code>
  4145. methods are as described for <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_traits.html"><code><phrase
  4146. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase
  4147. role="special">::</phrase><phrase role="identifier">stack_traits</phrase></code></ulink>.
  4148. </para>
  4149. <para>
  4150. <bridgehead renderas="sect4" id="class_protected_fixedsize_stack_bridgehead">
  4151. <phrase id="class_protected_fixedsize_stack"/>
  4152. <link linkend="class_protected_fixedsize_stack">Class
  4153. <code>protected_fixedsize_stack</code></link>
  4154. </bridgehead>
  4155. </para>
  4156. <para>
  4157. <emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> which
  4158. models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator
  4159. concept</emphasis></link>. It appends a guard page at the end of each stack
  4160. to protect against exceeding the stack. If the guard page is accessed (read
  4161. or write operation) a segmentation fault/access violation is generated by the
  4162. operating system.
  4163. </para>
  4164. <important>
  4165. <para>
  4166. Using <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> is expensive.
  4167. Launching a new fiber with a stack of this type incurs the overhead of setting
  4168. the memory protection; once allocated, this stack is just as efficient to
  4169. use as <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link>.
  4170. </para>
  4171. </important>
  4172. <note>
  4173. <para>
  4174. The appended <code><phrase role="identifier">guard</phrase> <phrase role="identifier">page</phrase></code>
  4175. is <emphasis role="bold">not</emphasis> mapped to physical memory, only virtual
  4176. addresses are used.
  4177. </para>
  4178. </note>
  4179. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">protected_fixedsize</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  4180. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  4181. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  4182. <phrase role="keyword">struct</phrase> <phrase role="identifier">protected_fixedsize</phrase> <phrase role="special">{</phrase>
  4183. <phrase role="identifier">protected_fixesize</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">());</phrase>
  4184. <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
  4185. <phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;);</phrase>
  4186. <phrase role="special">}</phrase>
  4187. <phrase role="special">}}</phrase>
  4188. </programlisting>
  4189. <para>
  4190. <bridgehead renderas="sect4" id="protected_fixedsize_allocate_bridgehead">
  4191. <phrase id="protected_fixedsize_allocate"/>
  4192. <link linkend="protected_fixedsize_allocate">Member
  4193. function <code>allocate</code>()</link>
  4194. </bridgehead>
  4195. </para>
  4196. <programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
  4197. </programlisting>
  4198. <variablelist>
  4199. <title></title>
  4200. <varlistentry>
  4201. <term>Preconditions:</term>
  4202. <listitem>
  4203. <para>
  4204. <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
  4205. role="identifier">minimum_size</phrase><phrase role="special">()</phrase>
  4206. <phrase role="special">&lt;=</phrase> <phrase role="identifier">size</phrase></code>
  4207. and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
  4208. role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
  4209. <phrase role="special">||</phrase> <phrase role="special">(</phrase>
  4210. <phrase role="identifier">size</phrase> <phrase role="special">&lt;=</phrase>
  4211. <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
  4212. role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
  4213. <phrase role="special">)</phrase></code>.
  4214. </para>
  4215. </listitem>
  4216. </varlistentry>
  4217. <varlistentry>
  4218. <term>Effects:</term>
  4219. <listitem>
  4220. <para>
  4221. Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
  4222. bytes and stores a pointer to the stack and its actual size in <code><phrase
  4223. role="identifier">sctx</phrase></code>. Depending on the architecture
  4224. (the stack grows downwards/upwards) the stored address is the highest/lowest
  4225. address of the stack.
  4226. </para>
  4227. </listitem>
  4228. </varlistentry>
  4229. </variablelist>
  4230. <para>
  4231. <bridgehead renderas="sect4" id="protected_fixesize_deallocate_bridgehead">
  4232. <phrase id="protected_fixesize_deallocate"/>
  4233. <link linkend="protected_fixesize_deallocate">Member
  4234. function <code>deallocate</code>()</link>
  4235. </bridgehead>
  4236. </para>
  4237. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">);</phrase>
  4238. </programlisting>
  4239. <variablelist>
  4240. <title></title>
  4241. <varlistentry>
  4242. <term>Preconditions:</term>
  4243. <listitem>
  4244. <para>
  4245. <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
  4246. role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
  4247. role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase
  4248. role="special">()</phrase> <phrase role="special">&lt;=</phrase> <phrase
  4249. role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
  4250. role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase
  4251. role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
  4252. role="special">()</phrase> <phrase role="special">||</phrase> <phrase
  4253. role="special">(</phrase> <phrase role="identifier">sctx</phrase><phrase
  4254. role="special">.</phrase><phrase role="identifier">size</phrase> <phrase
  4255. role="special">&lt;=</phrase> <phrase role="identifier">traits_type</phrase><phrase
  4256. role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
  4257. role="special">()</phrase> <phrase role="special">)</phrase></code>.
  4258. </para>
  4259. </listitem>
  4260. </varlistentry>
  4261. <varlistentry>
  4262. <term>Effects:</term>
  4263. <listitem>
  4264. <para>
  4265. Deallocates the stack space.
  4266. </para>
  4267. </listitem>
  4268. </varlistentry>
  4269. </variablelist>
  4270. <para>
  4271. <bridgehead renderas="sect4" id="class_pooled_fixedsize_stack_bridgehead">
  4272. <phrase id="class_pooled_fixedsize_stack"/>
  4273. <link linkend="class_pooled_fixedsize_stack">Class
  4274. <code>pooled_fixedsize_stack</code></link>
  4275. </bridgehead>
  4276. </para>
  4277. <para>
  4278. <emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_pooled_fixedsize_stack"><code>pooled_fixedsize_stack</code></link> which
  4279. models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator
  4280. concept</emphasis></link>. In contrast to <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> it
  4281. does not append a guard page at the end of each stack. The memory is managed
  4282. internally by <ulink url="http://www.boost.org/doc/libs/release/libs/pool/doc/html/boost/pool.html"><code><phrase
  4283. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase
  4284. role="special">&lt;&gt;</phrase></code></ulink>.
  4285. </para>
  4286. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">pooled_fixedsize_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  4287. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  4288. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  4289. <phrase role="keyword">struct</phrase> <phrase role="identifier">pooled_fixedsize_stack</phrase> <phrase role="special">{</phrase>
  4290. <phrase role="identifier">pooled_fixedsize_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">stack_size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">(),</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">next_size</phrase> <phrase role="special">=</phrase> <phrase role="number">32</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">max_size</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
  4291. <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
  4292. <phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;);</phrase>
  4293. <phrase role="special">}</phrase>
  4294. <phrase role="special">}}</phrase>
  4295. </programlisting>
  4296. <para>
  4297. <bridgehead renderas="sect4" id="pooled_fixedsize_bridgehead">
  4298. <phrase id="pooled_fixedsize"/>
  4299. <link linkend="pooled_fixedsize">Constructor</link>
  4300. </bridgehead>
  4301. </para>
  4302. <programlisting><phrase role="identifier">pooled_fixedsize_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">stack_size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">next_size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">max_size</phrase><phrase role="special">);</phrase>
  4303. </programlisting>
  4304. <variablelist>
  4305. <title></title>
  4306. <varlistentry>
  4307. <term>Preconditions:</term>
  4308. <listitem>
  4309. <para>
  4310. <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
  4311. role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
  4312. <phrase role="special">||</phrase> <phrase role="special">(</phrase>
  4313. <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
  4314. role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
  4315. <phrase role="special">&gt;=</phrase> <phrase role="identifier">stack_size</phrase><phrase
  4316. role="special">)</phrase></code> and <code><phrase role="number">0</phrase>
  4317. <phrase role="special">&lt;</phrase> <phrase role="identifier">next_size</phrase></code>.
  4318. </para>
  4319. </listitem>
  4320. </varlistentry>
  4321. <varlistentry>
  4322. <term>Effects:</term>
  4323. <listitem>
  4324. <para>
  4325. Allocates memory of at least <code><phrase role="identifier">stack_size</phrase></code>
  4326. bytes and stores a pointer to the stack and its actual size in <code><phrase
  4327. role="identifier">sctx</phrase></code>. Depending on the architecture
  4328. (the stack grows downwards/upwards) the stored address is the highest/lowest
  4329. address of the stack. Argument <code><phrase role="identifier">next_size</phrase></code>
  4330. determines the number of stacks to request from the system the first
  4331. time that <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  4332. needs to allocate system memory. The third argument <code><phrase role="identifier">max_size</phrase></code>
  4333. controls how much memory might be allocated for stacks &mdash; a value of zero
  4334. means no upper limit.
  4335. </para>
  4336. </listitem>
  4337. </varlistentry>
  4338. </variablelist>
  4339. <para>
  4340. <bridgehead renderas="sect4" id="pooled_fixedsize_allocate_bridgehead">
  4341. <phrase id="pooled_fixedsize_allocate"/>
  4342. <link linkend="pooled_fixedsize_allocate">Member
  4343. function <code>allocate</code>()</link>
  4344. </bridgehead>
  4345. </para>
  4346. <programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
  4347. </programlisting>
  4348. <variablelist>
  4349. <title></title>
  4350. <varlistentry>
  4351. <term>Preconditions:</term>
  4352. <listitem>
  4353. <para>
  4354. <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
  4355. role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
  4356. <phrase role="special">||</phrase> <phrase role="special">(</phrase>
  4357. <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
  4358. role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
  4359. <phrase role="special">&gt;=</phrase> <phrase role="identifier">stack_size</phrase><phrase
  4360. role="special">)</phrase></code>.
  4361. </para>
  4362. </listitem>
  4363. </varlistentry>
  4364. <varlistentry>
  4365. <term>Effects:</term>
  4366. <listitem>
  4367. <para>
  4368. Allocates memory of at least <code><phrase role="identifier">stack_size</phrase></code>
  4369. bytes and stores a pointer to the stack and its actual size in <code><phrase
  4370. role="identifier">sctx</phrase></code>. Depending on the architecture
  4371. (the stack grows downwards/upwards) the stored address is the highest/lowest
  4372. address of the stack.
  4373. </para>
  4374. </listitem>
  4375. </varlistentry>
  4376. </variablelist>
  4377. <para>
  4378. <bridgehead renderas="sect4" id="pooled_fixesize_deallocate_bridgehead">
  4379. <phrase id="pooled_fixesize_deallocate"/>
  4380. <link linkend="pooled_fixesize_deallocate">Member
  4381. function <code>deallocate</code>()</link>
  4382. </bridgehead>
  4383. </para>
  4384. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">);</phrase>
  4385. </programlisting>
  4386. <variablelist>
  4387. <title></title>
  4388. <varlistentry>
  4389. <term>Preconditions:</term>
  4390. <listitem>
  4391. <para>
  4392. <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
  4393. role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
  4394. role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
  4395. role="special">()</phrase> <phrase role="special">||</phrase> <phrase
  4396. role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
  4397. role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
  4398. role="special">()</phrase> <phrase role="special">&gt;=</phrase> <phrase
  4399. role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
  4400. role="identifier">size</phrase><phrase role="special">)</phrase></code>.
  4401. </para>
  4402. </listitem>
  4403. </varlistentry>
  4404. <varlistentry>
  4405. <term>Effects:</term>
  4406. <listitem>
  4407. <para>
  4408. Deallocates the stack space.
  4409. </para>
  4410. </listitem>
  4411. </varlistentry>
  4412. </variablelist>
  4413. <note>
  4414. <para>
  4415. This stack allocator is not thread safe.
  4416. </para>
  4417. </note>
  4418. <para>
  4419. <bridgehead renderas="sect4" id="class_fixedsize_stack_bridgehead">
  4420. <phrase id="class_fixedsize_stack"/>
  4421. <link linkend="class_fixedsize_stack">Class
  4422. <code>fixedsize_stack</code></link>
  4423. </bridgehead>
  4424. </para>
  4425. <para>
  4426. <emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link> which
  4427. models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator
  4428. concept</emphasis></link>. In contrast to <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> it
  4429. does not append a guard page at the end of each stack. The memory is simply
  4430. managed by <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  4431. role="identifier">malloc</phrase><phrase role="special">()</phrase></code>
  4432. and <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  4433. role="identifier">free</phrase><phrase role="special">()</phrase></code>.
  4434. </para>
  4435. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">/</phrase><phrase role="identifier">fixedsize_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  4436. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  4437. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  4438. <phrase role="keyword">struct</phrase> <phrase role="identifier">fixedsize_stack</phrase> <phrase role="special">{</phrase>
  4439. <phrase role="identifier">fixedsize_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">());</phrase>
  4440. <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
  4441. <phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;);</phrase>
  4442. <phrase role="special">}</phrase>
  4443. <phrase role="special">}}</phrase>
  4444. </programlisting>
  4445. <para>
  4446. <bridgehead renderas="sect4" id="fixedsize_allocate_bridgehead">
  4447. <phrase id="fixedsize_allocate"/>
  4448. <link linkend="fixedsize_allocate">Member function
  4449. <code>allocate</code>()</link>
  4450. </bridgehead>
  4451. </para>
  4452. <programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
  4453. </programlisting>
  4454. <variablelist>
  4455. <title></title>
  4456. <varlistentry>
  4457. <term>Preconditions:</term>
  4458. <listitem>
  4459. <para>
  4460. <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
  4461. role="identifier">minimum_size</phrase><phrase role="special">()</phrase>
  4462. <phrase role="special">&lt;=</phrase> <phrase role="identifier">size</phrase></code>
  4463. and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
  4464. role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
  4465. <phrase role="special">||</phrase> <phrase role="special">(</phrase>
  4466. <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
  4467. role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
  4468. <phrase role="special">&gt;=</phrase> <phrase role="identifier">size</phrase><phrase
  4469. role="special">)</phrase></code>.
  4470. </para>
  4471. </listitem>
  4472. </varlistentry>
  4473. <varlistentry>
  4474. <term>Effects:</term>
  4475. <listitem>
  4476. <para>
  4477. Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
  4478. bytes and stores a pointer to the stack and its actual size in <code><phrase
  4479. role="identifier">sctx</phrase></code>. Depending on the architecture
  4480. (the stack grows downwards/upwards) the stored address is the highest/lowest
  4481. address of the stack.
  4482. </para>
  4483. </listitem>
  4484. </varlistentry>
  4485. </variablelist>
  4486. <para>
  4487. <bridgehead renderas="sect4" id="fixesize_deallocate_bridgehead">
  4488. <phrase id="fixesize_deallocate"/>
  4489. <link linkend="fixesize_deallocate">Member
  4490. function <code>deallocate</code>()</link>
  4491. </bridgehead>
  4492. </para>
  4493. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">);</phrase>
  4494. </programlisting>
  4495. <variablelist>
  4496. <title></title>
  4497. <varlistentry>
  4498. <term>Preconditions:</term>
  4499. <listitem>
  4500. <para>
  4501. <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
  4502. role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
  4503. role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase
  4504. role="special">()</phrase> <phrase role="special">&lt;=</phrase> <phrase
  4505. role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
  4506. role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase
  4507. role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
  4508. role="special">()</phrase> <phrase role="special">||</phrase> <phrase
  4509. role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
  4510. role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
  4511. role="special">()</phrase> <phrase role="special">&gt;=</phrase> <phrase
  4512. role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
  4513. role="identifier">size</phrase><phrase role="special">)</phrase></code>.
  4514. </para>
  4515. </listitem>
  4516. </varlistentry>
  4517. <varlistentry>
  4518. <term>Effects:</term>
  4519. <listitem>
  4520. <para>
  4521. Deallocates the stack space.
  4522. </para>
  4523. </listitem>
  4524. </varlistentry>
  4525. </variablelist>
  4526. <para>
  4527. <anchor id="segmented"/><bridgehead renderas="sect4" id="class_segmented_stack_bridgehead">
  4528. <phrase id="class_segmented_stack"/>
  4529. <link linkend="class_segmented_stack">Class
  4530. <code>segmented_stack</code></link>
  4531. </bridgehead>
  4532. </para>
  4533. <para>
  4534. <emphasis role="bold">Boost.Fiber</emphasis> supports usage of a <link linkend="class_segmented_stack"><code>segmented_stack</code></link>,
  4535. i.e. the stack grows on demand. The fiber is created with a minimal stack size
  4536. which will be increased as required. Class <link linkend="class_segmented_stack"><code>segmented_stack</code></link> models
  4537. the <link linkend="stack_allocator_concept"><emphasis>stack-allocator concept</emphasis></link>.
  4538. In contrast to <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> and
  4539. <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link> it creates a stack which grows on demand.
  4540. </para>
  4541. <note>
  4542. <para>
  4543. Segmented stacks are currently only supported by <emphasis role="bold">gcc</emphasis>
  4544. from version <emphasis role="bold">4.7</emphasis> and <emphasis role="bold">clang</emphasis>
  4545. from version <emphasis role="bold">3.4</emphasis> onwards. In order to use
  4546. a <link linkend="class_segmented_stack"><code>segmented_stack</code></link> <emphasis role="bold">Boost.Fiber</emphasis>
  4547. must be built with property <code><phrase role="identifier">segmented</phrase><phrase
  4548. role="special">-</phrase><phrase role="identifier">stacks</phrase></code>,
  4549. e.g. <emphasis role="bold">toolset=gcc segmented-stacks=on</emphasis> and
  4550. applying BOOST_USE_SEGMENTED_STACKS at b2/bjam command line.
  4551. </para>
  4552. </note>
  4553. <note>
  4554. <para>
  4555. Segmented stacks can only be used with callcc() using property <code><phrase
  4556. role="identifier">context</phrase><phrase role="special">-</phrase><phrase
  4557. role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">ucontext</phrase></code>.
  4558. </para>
  4559. </note>
  4560. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">segmented_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  4561. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  4562. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  4563. <phrase role="keyword">struct</phrase> <phrase role="identifier">segmented_stack</phrase> <phrase role="special">{</phrase>
  4564. <phrase role="identifier">segmented_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">stack_size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">());</phrase>
  4565. <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
  4566. <phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;);</phrase>
  4567. <phrase role="special">}</phrase>
  4568. <phrase role="special">}}</phrase>
  4569. </programlisting>
  4570. <para>
  4571. <bridgehead renderas="sect4" id="segmented_allocate_bridgehead">
  4572. <phrase id="segmented_allocate"/>
  4573. <link linkend="segmented_allocate">Member function
  4574. <code>allocate</code>()</link>
  4575. </bridgehead>
  4576. </para>
  4577. <programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
  4578. </programlisting>
  4579. <variablelist>
  4580. <title></title>
  4581. <varlistentry>
  4582. <term>Preconditions:</term>
  4583. <listitem>
  4584. <para>
  4585. <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
  4586. role="identifier">minimum_size</phrase><phrase role="special">()</phrase>
  4587. <phrase role="special">&lt;=</phrase> <phrase role="identifier">size</phrase></code>
  4588. and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
  4589. role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
  4590. <phrase role="special">||</phrase> <phrase role="special">(</phrase>
  4591. <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
  4592. role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
  4593. <phrase role="special">&gt;=</phrase> <phrase role="identifier">size</phrase><phrase
  4594. role="special">)</phrase></code>.
  4595. </para>
  4596. </listitem>
  4597. </varlistentry>
  4598. <varlistentry>
  4599. <term>Effects:</term>
  4600. <listitem>
  4601. <para>
  4602. Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
  4603. bytes and stores a pointer to the stack and its actual size in <code><phrase
  4604. role="identifier">sctx</phrase></code>. Depending on the architecture
  4605. (the stack grows downwards/upwards) the stored address is the highest/lowest
  4606. address of the stack.
  4607. </para>
  4608. </listitem>
  4609. </varlistentry>
  4610. </variablelist>
  4611. <para>
  4612. <bridgehead renderas="sect4" id="segmented_deallocate_bridgehead">
  4613. <phrase id="segmented_deallocate"/>
  4614. <link linkend="segmented_deallocate">Member
  4615. function <code>deallocate</code>()</link>
  4616. </bridgehead>
  4617. </para>
  4618. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">);</phrase>
  4619. </programlisting>
  4620. <variablelist>
  4621. <title></title>
  4622. <varlistentry>
  4623. <term>Preconditions:</term>
  4624. <listitem>
  4625. <para>
  4626. <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
  4627. role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
  4628. role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase
  4629. role="special">()</phrase> <phrase role="special">&lt;=</phrase> <phrase
  4630. role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
  4631. role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase
  4632. role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
  4633. role="special">()</phrase> <phrase role="special">||</phrase> <phrase
  4634. role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
  4635. role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
  4636. role="special">()</phrase> <phrase role="special">&gt;=</phrase> <phrase
  4637. role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
  4638. role="identifier">size</phrase><phrase role="special">)</phrase></code>.
  4639. </para>
  4640. </listitem>
  4641. </varlistentry>
  4642. <varlistentry>
  4643. <term>Effects:</term>
  4644. <listitem>
  4645. <para>
  4646. Deallocates the stack space.
  4647. </para>
  4648. </listitem>
  4649. </varlistentry>
  4650. </variablelist>
  4651. <note>
  4652. <para>
  4653. If the library is compiled for segmented stacks, <link linkend="class_segmented_stack"><code>segmented_stack</code></link> is
  4654. the only available stack allocator.
  4655. </para>
  4656. </note>
  4657. <section id="fiber.stack.valgrind">
  4658. <title><link linkend="fiber.stack.valgrind">Support for valgrind</link></title>
  4659. <para>
  4660. Running programs that switch stacks under valgrind causes problems. Property
  4661. (b2 command-line) <code><phrase role="identifier">valgrind</phrase><phrase
  4662. role="special">=</phrase><phrase role="identifier">on</phrase></code> let
  4663. valgrind treat the memory regions as stack space which suppresses the errors.
  4664. </para>
  4665. </section>
  4666. </section>
  4667. <section id="fiber.synchronization">
  4668. <title><anchor id="synchronization"/><link linkend="fiber.synchronization">Synchronization</link></title>
  4669. <para>
  4670. In general, <emphasis role="bold">Boost.Fiber</emphasis> synchronization objects
  4671. can neither be moved nor copied. A synchronization object acts as a mutually-agreed
  4672. rendezvous point between different fibers. If such an object were copied somewhere
  4673. else, the new copy would have no consumers. If such an object were <emphasis>moved</emphasis>
  4674. somewhere else, leaving the original instance in an unspecified state, existing
  4675. consumers would behave strangely.
  4676. </para>
  4677. <para>
  4678. The fiber synchronization objects provided by this library will, by default,
  4679. safely synchronize fibers running on different threads. However, this level
  4680. of synchronization can be removed (for performance) by building the library
  4681. with <emphasis role="bold"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></emphasis>
  4682. defined. When the library is built with that macro, you must ensure that all
  4683. the fibers referencing a particular synchronization object are running in the
  4684. same thread.
  4685. </para>
  4686. <section id="fiber.synchronization.mutex_types">
  4687. <title><link linkend="fiber.synchronization.mutex_types">Mutex Types</link></title>
  4688. <para>
  4689. <bridgehead renderas="sect4" id="class_mutex_bridgehead">
  4690. <phrase id="class_mutex"/>
  4691. <link linkend="class_mutex">Class <code>mutex</code></link>
  4692. </bridgehead>
  4693. </para>
  4694. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">mutex</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  4695. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  4696. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  4697. <phrase role="keyword">class</phrase> <phrase role="identifier">mutex</phrase> <phrase role="special">{</phrase>
  4698. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  4699. <phrase role="identifier">mutex</phrase><phrase role="special">();</phrase>
  4700. <phrase role="special">~</phrase><phrase role="identifier">mutex</phrase><phrase role="special">();</phrase>
  4701. <phrase role="identifier">mutex</phrase><phrase role="special">(</phrase> <phrase role="identifier">mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  4702. <phrase role="identifier">mutex</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  4703. <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
  4704. <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
  4705. <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
  4706. <phrase role="special">};</phrase>
  4707. <phrase role="special">}}</phrase>
  4708. </programlisting>
  4709. <para>
  4710. <link linkend="class_mutex"><code>mutex</code></link> provides an exclusive-ownership mutex. At most one fiber
  4711. can own the lock on a given instance of <link linkend="class_mutex"><code>mutex</code></link> at any time. Multiple
  4712. concurrent calls to <code><phrase role="identifier">lock</phrase><phrase
  4713. role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase
  4714. role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase
  4715. role="special">()</phrase></code> shall be permitted.
  4716. </para>
  4717. <para>
  4718. Any fiber blocked in <code><phrase role="identifier">lock</phrase><phrase
  4719. role="special">()</phrase></code> is suspended until the owning fiber releases
  4720. the lock by calling <code><phrase role="identifier">unlock</phrase><phrase
  4721. role="special">()</phrase></code>.
  4722. </para>
  4723. <para>
  4724. <bridgehead renderas="sect4" id="mutex_lock_bridgehead">
  4725. <phrase id="mutex_lock"/>
  4726. <link linkend="mutex_lock">Member function <code>lock</code>()</link>
  4727. </bridgehead>
  4728. </para>
  4729. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
  4730. </programlisting>
  4731. <variablelist>
  4732. <title></title>
  4733. <varlistentry>
  4734. <term>Precondition:</term>
  4735. <listitem>
  4736. <para>
  4737. The calling fiber doesn't own the mutex.
  4738. </para>
  4739. </listitem>
  4740. </varlistentry>
  4741. <varlistentry>
  4742. <term>Effects:</term>
  4743. <listitem>
  4744. <para>
  4745. The current fiber blocks until ownership can be obtained.
  4746. </para>
  4747. </listitem>
  4748. </varlistentry>
  4749. <varlistentry>
  4750. <term>Throws:</term>
  4751. <listitem>
  4752. <para>
  4753. <code><phrase role="identifier">lock_error</phrase></code>
  4754. </para>
  4755. </listitem>
  4756. </varlistentry>
  4757. <varlistentry>
  4758. <term>Error Conditions:</term>
  4759. <listitem>
  4760. <para>
  4761. <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
  4762. <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  4763. role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
  4764. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  4765. already owns the mutex.
  4766. </para>
  4767. </listitem>
  4768. </varlistentry>
  4769. </variablelist>
  4770. <para>
  4771. <bridgehead renderas="sect4" id="mutex_try_lock_bridgehead">
  4772. <phrase id="mutex_try_lock"/>
  4773. <link linkend="mutex_try_lock">Member function <code>try_lock</code>()</link>
  4774. </bridgehead>
  4775. </para>
  4776. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
  4777. </programlisting>
  4778. <variablelist>
  4779. <title></title>
  4780. <varlistentry>
  4781. <term>Precondition:</term>
  4782. <listitem>
  4783. <para>
  4784. The calling fiber doesn't own the mutex.
  4785. </para>
  4786. </listitem>
  4787. </varlistentry>
  4788. <varlistentry>
  4789. <term>Effects:</term>
  4790. <listitem>
  4791. <para>
  4792. Attempt to obtain ownership for the current fiber without blocking.
  4793. </para>
  4794. </listitem>
  4795. </varlistentry>
  4796. <varlistentry>
  4797. <term>Returns:</term>
  4798. <listitem>
  4799. <para>
  4800. <code><phrase role="keyword">true</phrase></code> if ownership was
  4801. obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
  4802. otherwise.
  4803. </para>
  4804. </listitem>
  4805. </varlistentry>
  4806. <varlistentry>
  4807. <term>Throws:</term>
  4808. <listitem>
  4809. <para>
  4810. <code><phrase role="identifier">lock_error</phrase></code>
  4811. </para>
  4812. </listitem>
  4813. </varlistentry>
  4814. <varlistentry>
  4815. <term>Error Conditions:</term>
  4816. <listitem>
  4817. <para>
  4818. <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
  4819. <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  4820. role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
  4821. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  4822. already owns the mutex.
  4823. </para>
  4824. </listitem>
  4825. </varlistentry>
  4826. </variablelist>
  4827. <para>
  4828. <bridgehead renderas="sect4" id="mutex_unlock_bridgehead">
  4829. <phrase id="mutex_unlock"/>
  4830. <link linkend="mutex_unlock">Member function <code>unlock</code>()</link>
  4831. </bridgehead>
  4832. </para>
  4833. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
  4834. </programlisting>
  4835. <variablelist>
  4836. <title></title>
  4837. <varlistentry>
  4838. <term>Precondition:</term>
  4839. <listitem>
  4840. <para>
  4841. The current fiber owns <code><phrase role="special">*</phrase><phrase
  4842. role="keyword">this</phrase></code>.
  4843. </para>
  4844. </listitem>
  4845. </varlistentry>
  4846. <varlistentry>
  4847. <term>Effects:</term>
  4848. <listitem>
  4849. <para>
  4850. Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  4851. by the current fiber.
  4852. </para>
  4853. </listitem>
  4854. </varlistentry>
  4855. <varlistentry>
  4856. <term>Throws:</term>
  4857. <listitem>
  4858. <para>
  4859. <code><phrase role="identifier">lock_error</phrase></code>
  4860. </para>
  4861. </listitem>
  4862. </varlistentry>
  4863. <varlistentry>
  4864. <term>Error Conditions:</term>
  4865. <listitem>
  4866. <para>
  4867. <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase
  4868. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  4869. role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
  4870. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  4871. does not own the mutex.
  4872. </para>
  4873. </listitem>
  4874. </varlistentry>
  4875. </variablelist>
  4876. <para>
  4877. <bridgehead renderas="sect4" id="class_timed_mutex_bridgehead">
  4878. <phrase id="class_timed_mutex"/>
  4879. <link linkend="class_timed_mutex">Class <code>timed_mutex</code></link>
  4880. </bridgehead>
  4881. </para>
  4882. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">timed_mutex</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  4883. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  4884. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  4885. <phrase role="keyword">class</phrase> <phrase role="identifier">timed_mutex</phrase> <phrase role="special">{</phrase>
  4886. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  4887. <phrase role="identifier">timed_mutex</phrase><phrase role="special">();</phrase>
  4888. <phrase role="special">~</phrase><phrase role="identifier">timed_mutex</phrase><phrase role="special">();</phrase>
  4889. <phrase role="identifier">timed_mutex</phrase><phrase role="special">(</phrase> <phrase role="identifier">timed_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  4890. <phrase role="identifier">timed_mutex</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">timed_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  4891. <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
  4892. <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
  4893. <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
  4894. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  4895. <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
  4896. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  4897. <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
  4898. <phrase role="special">};</phrase>
  4899. <phrase role="special">}}</phrase>
  4900. </programlisting>
  4901. <para>
  4902. <link linkend="class_timed_mutex"><code>timed_mutex</code></link> provides an exclusive-ownership mutex. At most
  4903. one fiber can own the lock on a given instance of <link linkend="class_timed_mutex"><code>timed_mutex</code></link> at
  4904. any time. Multiple concurrent calls to <code><phrase role="identifier">lock</phrase><phrase
  4905. role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase
  4906. role="special">()</phrase></code>, <code><phrase role="identifier">try_lock_until</phrase><phrase
  4907. role="special">()</phrase></code>, <code><phrase role="identifier">try_lock_for</phrase><phrase
  4908. role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase
  4909. role="special">()</phrase></code> shall be permitted.
  4910. </para>
  4911. <para>
  4912. <bridgehead renderas="sect4" id="timed_mutex_lock_bridgehead">
  4913. <phrase id="timed_mutex_lock"/>
  4914. <link linkend="timed_mutex_lock">Member function
  4915. <code>lock</code>()</link>
  4916. </bridgehead>
  4917. </para>
  4918. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
  4919. </programlisting>
  4920. <variablelist>
  4921. <title></title>
  4922. <varlistentry>
  4923. <term>Precondition:</term>
  4924. <listitem>
  4925. <para>
  4926. The calling fiber doesn't own the mutex.
  4927. </para>
  4928. </listitem>
  4929. </varlistentry>
  4930. <varlistentry>
  4931. <term>Effects:</term>
  4932. <listitem>
  4933. <para>
  4934. The current fiber blocks until ownership can be obtained.
  4935. </para>
  4936. </listitem>
  4937. </varlistentry>
  4938. <varlistentry>
  4939. <term>Throws:</term>
  4940. <listitem>
  4941. <para>
  4942. <code><phrase role="identifier">lock_error</phrase></code>
  4943. </para>
  4944. </listitem>
  4945. </varlistentry>
  4946. <varlistentry>
  4947. <term>Error Conditions:</term>
  4948. <listitem>
  4949. <para>
  4950. <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
  4951. <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  4952. role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
  4953. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  4954. already owns the mutex.
  4955. </para>
  4956. </listitem>
  4957. </varlistentry>
  4958. </variablelist>
  4959. <para>
  4960. <bridgehead renderas="sect4" id="timed_mutex_try_lock_bridgehead">
  4961. <phrase id="timed_mutex_try_lock"/>
  4962. <link linkend="timed_mutex_try_lock">Member
  4963. function <code>try_lock</code>()</link>
  4964. </bridgehead>
  4965. </para>
  4966. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
  4967. </programlisting>
  4968. <variablelist>
  4969. <title></title>
  4970. <varlistentry>
  4971. <term>Precondition:</term>
  4972. <listitem>
  4973. <para>
  4974. The calling fiber doesn't own the mutex.
  4975. </para>
  4976. </listitem>
  4977. </varlistentry>
  4978. <varlistentry>
  4979. <term>Effects:</term>
  4980. <listitem>
  4981. <para>
  4982. Attempt to obtain ownership for the current fiber without blocking.
  4983. </para>
  4984. </listitem>
  4985. </varlistentry>
  4986. <varlistentry>
  4987. <term>Returns:</term>
  4988. <listitem>
  4989. <para>
  4990. <code><phrase role="keyword">true</phrase></code> if ownership was
  4991. obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
  4992. otherwise.
  4993. </para>
  4994. </listitem>
  4995. </varlistentry>
  4996. <varlistentry>
  4997. <term>Throws:</term>
  4998. <listitem>
  4999. <para>
  5000. <code><phrase role="identifier">lock_error</phrase></code>
  5001. </para>
  5002. </listitem>
  5003. </varlistentry>
  5004. <varlistentry>
  5005. <term>Error Conditions:</term>
  5006. <listitem>
  5007. <para>
  5008. <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
  5009. <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  5010. role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
  5011. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  5012. already owns the mutex.
  5013. </para>
  5014. </listitem>
  5015. </varlistentry>
  5016. </variablelist>
  5017. <para>
  5018. <bridgehead renderas="sect4" id="timed_mutex_unlock_bridgehead">
  5019. <phrase id="timed_mutex_unlock"/>
  5020. <link linkend="timed_mutex_unlock">Member function
  5021. <code>unlock</code>()</link>
  5022. </bridgehead>
  5023. </para>
  5024. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
  5025. </programlisting>
  5026. <variablelist>
  5027. <title></title>
  5028. <varlistentry>
  5029. <term>Precondition:</term>
  5030. <listitem>
  5031. <para>
  5032. The current fiber owns <code><phrase role="special">*</phrase><phrase
  5033. role="keyword">this</phrase></code>.
  5034. </para>
  5035. </listitem>
  5036. </varlistentry>
  5037. <varlistentry>
  5038. <term>Effects:</term>
  5039. <listitem>
  5040. <para>
  5041. Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  5042. by the current fiber.
  5043. </para>
  5044. </listitem>
  5045. </varlistentry>
  5046. <varlistentry>
  5047. <term>Throws:</term>
  5048. <listitem>
  5049. <para>
  5050. <code><phrase role="identifier">lock_error</phrase></code>
  5051. </para>
  5052. </listitem>
  5053. </varlistentry>
  5054. <varlistentry>
  5055. <term>Error Conditions:</term>
  5056. <listitem>
  5057. <para>
  5058. <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase
  5059. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  5060. role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
  5061. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  5062. does not own the mutex.
  5063. </para>
  5064. </listitem>
  5065. </varlistentry>
  5066. </variablelist>
  5067. <para>
  5068. <bridgehead renderas="sect4" id="timed_mutex_try_lock_until_bridgehead">
  5069. <phrase id="timed_mutex_try_lock_until"/>
  5070. <link linkend="timed_mutex_try_lock_until">Templated
  5071. member function <code>try_lock_until</code>()</link>
  5072. </bridgehead>
  5073. </para>
  5074. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  5075. <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
  5076. </programlisting>
  5077. <variablelist>
  5078. <title></title>
  5079. <varlistentry>
  5080. <term>Precondition:</term>
  5081. <listitem>
  5082. <para>
  5083. The calling fiber doesn't own the mutex.
  5084. </para>
  5085. </listitem>
  5086. </varlistentry>
  5087. <varlistentry>
  5088. <term>Effects:</term>
  5089. <listitem>
  5090. <para>
  5091. Attempt to obtain ownership for the current fiber. Blocks until ownership
  5092. can be obtained, or the specified time is reached. If the specified
  5093. time has already passed, behaves as <link linkend="timed_mutex_try_lock"><code>timed_mutex::try_lock()</code></link>.
  5094. </para>
  5095. </listitem>
  5096. </varlistentry>
  5097. <varlistentry>
  5098. <term>Returns:</term>
  5099. <listitem>
  5100. <para>
  5101. <code><phrase role="keyword">true</phrase></code> if ownership was
  5102. obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
  5103. otherwise.
  5104. </para>
  5105. </listitem>
  5106. </varlistentry>
  5107. <varlistentry>
  5108. <term>Throws:</term>
  5109. <listitem>
  5110. <para>
  5111. <code><phrase role="identifier">lock_error</phrase></code>, timeout-related
  5112. exceptions.
  5113. </para>
  5114. </listitem>
  5115. </varlistentry>
  5116. <varlistentry>
  5117. <term>Error Conditions:</term>
  5118. <listitem>
  5119. <para>
  5120. <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
  5121. <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  5122. role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
  5123. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  5124. already owns the mutex.
  5125. </para>
  5126. </listitem>
  5127. </varlistentry>
  5128. </variablelist>
  5129. <para>
  5130. <bridgehead renderas="sect4" id="timed_mutex_try_lock_for_bridgehead">
  5131. <phrase id="timed_mutex_try_lock_for"/>
  5132. <link linkend="timed_mutex_try_lock_for">Templated
  5133. member function <code>try_lock_for</code>()</link>
  5134. </bridgehead>
  5135. </para>
  5136. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  5137. <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
  5138. </programlisting>
  5139. <variablelist>
  5140. <title></title>
  5141. <varlistentry>
  5142. <term>Precondition:</term>
  5143. <listitem>
  5144. <para>
  5145. The calling fiber doesn't own the mutex.
  5146. </para>
  5147. </listitem>
  5148. </varlistentry>
  5149. <varlistentry>
  5150. <term>Effects:</term>
  5151. <listitem>
  5152. <para>
  5153. Attempt to obtain ownership for the current fiber. Blocks until ownership
  5154. can be obtained, or the specified time is reached. If the specified
  5155. time has already passed, behaves as <link linkend="timed_mutex_try_lock"><code>timed_mutex::try_lock()</code></link>.
  5156. </para>
  5157. </listitem>
  5158. </varlistentry>
  5159. <varlistentry>
  5160. <term>Returns:</term>
  5161. <listitem>
  5162. <para>
  5163. <code><phrase role="keyword">true</phrase></code> if ownership was
  5164. obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
  5165. otherwise.
  5166. </para>
  5167. </listitem>
  5168. </varlistentry>
  5169. <varlistentry>
  5170. <term>Throws:</term>
  5171. <listitem>
  5172. <para>
  5173. <code><phrase role="identifier">lock_error</phrase></code>, timeout-related
  5174. exceptions.
  5175. </para>
  5176. </listitem>
  5177. </varlistentry>
  5178. <varlistentry>
  5179. <term>Error Conditions:</term>
  5180. <listitem>
  5181. <para>
  5182. <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
  5183. <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  5184. role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
  5185. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  5186. already owns the mutex.
  5187. </para>
  5188. </listitem>
  5189. </varlistentry>
  5190. </variablelist>
  5191. <para>
  5192. <bridgehead renderas="sect4" id="class_recursive_mutex_bridgehead">
  5193. <phrase id="class_recursive_mutex"/>
  5194. <link linkend="class_recursive_mutex">Class
  5195. <code>recursive_mutex</code></link>
  5196. </bridgehead>
  5197. </para>
  5198. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">recursive_mutex</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  5199. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  5200. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  5201. <phrase role="keyword">class</phrase> <phrase role="identifier">recursive_mutex</phrase> <phrase role="special">{</phrase>
  5202. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  5203. <phrase role="identifier">recursive_mutex</phrase><phrase role="special">();</phrase>
  5204. <phrase role="special">~</phrase><phrase role="identifier">recursive_mutex</phrase><phrase role="special">();</phrase>
  5205. <phrase role="identifier">recursive_mutex</phrase><phrase role="special">(</phrase> <phrase role="identifier">recursive_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  5206. <phrase role="identifier">recursive_mutex</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">recursive_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  5207. <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
  5208. <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  5209. <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
  5210. <phrase role="special">};</phrase>
  5211. <phrase role="special">}}</phrase>
  5212. </programlisting>
  5213. <para>
  5214. <link linkend="class_recursive_mutex"><code>recursive_mutex</code></link> provides an exclusive-ownership recursive
  5215. mutex. At most one fiber can own the lock on a given instance of <link linkend="class_recursive_mutex"><code>recursive_mutex</code></link> at
  5216. any time. Multiple concurrent calls to <code><phrase role="identifier">lock</phrase><phrase
  5217. role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase
  5218. role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase
  5219. role="special">()</phrase></code> shall be permitted. A fiber that already
  5220. has exclusive ownership of a given <link linkend="class_recursive_mutex"><code>recursive_mutex</code></link> instance
  5221. can call <code><phrase role="identifier">lock</phrase><phrase role="special">()</phrase></code>
  5222. or <code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>
  5223. to acquire an additional level of ownership of the mutex. <code><phrase role="identifier">unlock</phrase><phrase
  5224. role="special">()</phrase></code> must be called once for each level of ownership
  5225. acquired by a single fiber before ownership can be acquired by another fiber.
  5226. </para>
  5227. <para>
  5228. <bridgehead renderas="sect4" id="recursive_mutex_lock_bridgehead">
  5229. <phrase id="recursive_mutex_lock"/>
  5230. <link linkend="recursive_mutex_lock">Member
  5231. function <code>lock</code>()</link>
  5232. </bridgehead>
  5233. </para>
  5234. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
  5235. </programlisting>
  5236. <variablelist>
  5237. <title></title>
  5238. <varlistentry>
  5239. <term>Effects:</term>
  5240. <listitem>
  5241. <para>
  5242. The current fiber blocks until ownership can be obtained.
  5243. </para>
  5244. </listitem>
  5245. </varlistentry>
  5246. <varlistentry>
  5247. <term>Throws:</term>
  5248. <listitem>
  5249. <para>
  5250. Nothing
  5251. </para>
  5252. </listitem>
  5253. </varlistentry>
  5254. </variablelist>
  5255. <para>
  5256. <bridgehead renderas="sect4" id="recursive_mutex_try_lock_bridgehead">
  5257. <phrase id="recursive_mutex_try_lock"/>
  5258. <link linkend="recursive_mutex_try_lock">Member
  5259. function <code>try_lock</code>()</link>
  5260. </bridgehead>
  5261. </para>
  5262. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  5263. </programlisting>
  5264. <variablelist>
  5265. <title></title>
  5266. <varlistentry>
  5267. <term>Effects:</term>
  5268. <listitem>
  5269. <para>
  5270. Attempt to obtain ownership for the current fiber without blocking.
  5271. </para>
  5272. </listitem>
  5273. </varlistentry>
  5274. <varlistentry>
  5275. <term>Returns:</term>
  5276. <listitem>
  5277. <para>
  5278. <code><phrase role="keyword">true</phrase></code> if ownership was
  5279. obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
  5280. otherwise.
  5281. </para>
  5282. </listitem>
  5283. </varlistentry>
  5284. <varlistentry>
  5285. <term>Throws:</term>
  5286. <listitem>
  5287. <para>
  5288. Nothing.
  5289. </para>
  5290. </listitem>
  5291. </varlistentry>
  5292. </variablelist>
  5293. <para>
  5294. <bridgehead renderas="sect4" id="recursive_mutex_unlock_bridgehead">
  5295. <phrase id="recursive_mutex_unlock"/>
  5296. <link linkend="recursive_mutex_unlock">Member
  5297. function <code>unlock</code>()</link>
  5298. </bridgehead>
  5299. </para>
  5300. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
  5301. </programlisting>
  5302. <variablelist>
  5303. <title></title>
  5304. <varlistentry>
  5305. <term>Effects:</term>
  5306. <listitem>
  5307. <para>
  5308. Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  5309. by the current fiber.
  5310. </para>
  5311. </listitem>
  5312. </varlistentry>
  5313. <varlistentry>
  5314. <term>Throws:</term>
  5315. <listitem>
  5316. <para>
  5317. <code><phrase role="identifier">lock_error</phrase></code>
  5318. </para>
  5319. </listitem>
  5320. </varlistentry>
  5321. <varlistentry>
  5322. <term>Error Conditions:</term>
  5323. <listitem>
  5324. <para>
  5325. <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase
  5326. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  5327. role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
  5328. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  5329. does not own the mutex.
  5330. </para>
  5331. </listitem>
  5332. </varlistentry>
  5333. </variablelist>
  5334. <para>
  5335. <bridgehead renderas="sect4" id="class_recursive_timed_mutex_bridgehead">
  5336. <phrase id="class_recursive_timed_mutex"/>
  5337. <link linkend="class_recursive_timed_mutex">Class
  5338. <code>recursive_timed_mutex</code></link>
  5339. </bridgehead>
  5340. </para>
  5341. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  5342. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  5343. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  5344. <phrase role="keyword">class</phrase> <phrase role="identifier">recursive_timed_mutex</phrase> <phrase role="special">{</phrase>
  5345. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  5346. <phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">();</phrase>
  5347. <phrase role="special">~</phrase><phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">();</phrase>
  5348. <phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">(</phrase> <phrase role="identifier">recursive_timed_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  5349. <phrase role="identifier">recursive_timed_mutex</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">recursive_timed_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  5350. <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
  5351. <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  5352. <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
  5353. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  5354. <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
  5355. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  5356. <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
  5357. <phrase role="special">};</phrase>
  5358. <phrase role="special">}}</phrase>
  5359. </programlisting>
  5360. <para>
  5361. <link linkend="class_recursive_timed_mutex"><code>recursive_timed_mutex</code></link> provides an exclusive-ownership
  5362. recursive mutex. At most one fiber can own the lock on a given instance of
  5363. <link linkend="class_recursive_timed_mutex"><code>recursive_timed_mutex</code></link> at any time. Multiple concurrent
  5364. calls to <code><phrase role="identifier">lock</phrase><phrase role="special">()</phrase></code>,
  5365. <code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>,
  5366. <code><phrase role="identifier">try_lock_for</phrase><phrase role="special">()</phrase></code>,
  5367. <code><phrase role="identifier">try_lock_until</phrase><phrase role="special">()</phrase></code>
  5368. and <code><phrase role="identifier">unlock</phrase><phrase role="special">()</phrase></code>
  5369. shall be permitted. A fiber that already has exclusive ownership of a given
  5370. <link linkend="class_recursive_timed_mutex"><code>recursive_timed_mutex</code></link> instance can call <code><phrase
  5371. role="identifier">lock</phrase><phrase role="special">()</phrase></code>,
  5372. <code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>,
  5373. <code><phrase role="identifier">try_lock_for</phrase><phrase role="special">()</phrase></code>
  5374. or <code><phrase role="identifier">try_lock_until</phrase><phrase role="special">()</phrase></code>
  5375. to acquire an additional level of ownership of the mutex. <code><phrase role="identifier">unlock</phrase><phrase
  5376. role="special">()</phrase></code> must be called once for each level of ownership
  5377. acquired by a single fiber before ownership can be acquired by another fiber.
  5378. </para>
  5379. <para>
  5380. <bridgehead renderas="sect4" id="recursive_timed_mutex_lock_bridgehead">
  5381. <phrase id="recursive_timed_mutex_lock"/>
  5382. <link linkend="recursive_timed_mutex_lock">Member
  5383. function <code>lock</code>()</link>
  5384. </bridgehead>
  5385. </para>
  5386. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
  5387. </programlisting>
  5388. <variablelist>
  5389. <title></title>
  5390. <varlistentry>
  5391. <term>Effects:</term>
  5392. <listitem>
  5393. <para>
  5394. The current fiber blocks until ownership can be obtained.
  5395. </para>
  5396. </listitem>
  5397. </varlistentry>
  5398. <varlistentry>
  5399. <term>Throws:</term>
  5400. <listitem>
  5401. <para>
  5402. Nothing
  5403. </para>
  5404. </listitem>
  5405. </varlistentry>
  5406. </variablelist>
  5407. <para>
  5408. <bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_bridgehead">
  5409. <phrase id="recursive_timed_mutex_try_lock"/>
  5410. <link linkend="recursive_timed_mutex_try_lock">Member
  5411. function <code>try_lock</code>()</link>
  5412. </bridgehead>
  5413. </para>
  5414. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  5415. </programlisting>
  5416. <variablelist>
  5417. <title></title>
  5418. <varlistentry>
  5419. <term>Effects:</term>
  5420. <listitem>
  5421. <para>
  5422. Attempt to obtain ownership for the current fiber without blocking.
  5423. </para>
  5424. </listitem>
  5425. </varlistentry>
  5426. <varlistentry>
  5427. <term>Returns:</term>
  5428. <listitem>
  5429. <para>
  5430. <code><phrase role="keyword">true</phrase></code> if ownership was
  5431. obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
  5432. otherwise.
  5433. </para>
  5434. </listitem>
  5435. </varlistentry>
  5436. <varlistentry>
  5437. <term>Throws:</term>
  5438. <listitem>
  5439. <para>
  5440. Nothing.
  5441. </para>
  5442. </listitem>
  5443. </varlistentry>
  5444. </variablelist>
  5445. <para>
  5446. <bridgehead renderas="sect4" id="recursive_timed_mutex_unlock_bridgehead">
  5447. <phrase id="recursive_timed_mutex_unlock"/>
  5448. <link linkend="recursive_timed_mutex_unlock">Member
  5449. function <code>unlock</code>()</link>
  5450. </bridgehead>
  5451. </para>
  5452. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
  5453. </programlisting>
  5454. <variablelist>
  5455. <title></title>
  5456. <varlistentry>
  5457. <term>Effects:</term>
  5458. <listitem>
  5459. <para>
  5460. Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  5461. by the current fiber.
  5462. </para>
  5463. </listitem>
  5464. </varlistentry>
  5465. <varlistentry>
  5466. <term>Throws:</term>
  5467. <listitem>
  5468. <para>
  5469. <code><phrase role="identifier">lock_error</phrase></code>
  5470. </para>
  5471. </listitem>
  5472. </varlistentry>
  5473. <varlistentry>
  5474. <term>Error Conditions:</term>
  5475. <listitem>
  5476. <para>
  5477. <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase
  5478. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  5479. role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
  5480. role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
  5481. does not own the mutex.
  5482. </para>
  5483. </listitem>
  5484. </varlistentry>
  5485. </variablelist>
  5486. <para>
  5487. <bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_until_bridgehead">
  5488. <phrase id="recursive_timed_mutex_try_lock_until"/>
  5489. <link linkend="recursive_timed_mutex_try_lock_until">Templated
  5490. member function <code>try_lock_until</code>()</link>
  5491. </bridgehead>
  5492. </para>
  5493. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  5494. <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
  5495. </programlisting>
  5496. <variablelist>
  5497. <title></title>
  5498. <varlistentry>
  5499. <term>Effects:</term>
  5500. <listitem>
  5501. <para>
  5502. Attempt to obtain ownership for the current fiber. Blocks until ownership
  5503. can be obtained, or the specified time is reached. If the specified
  5504. time has already passed, behaves as <link linkend="recursive_timed_mutex_try_lock"><code>recursive_timed_mutex::try_lock()</code></link>.
  5505. </para>
  5506. </listitem>
  5507. </varlistentry>
  5508. <varlistentry>
  5509. <term>Returns:</term>
  5510. <listitem>
  5511. <para>
  5512. <code><phrase role="keyword">true</phrase></code> if ownership was
  5513. obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
  5514. otherwise.
  5515. </para>
  5516. </listitem>
  5517. </varlistentry>
  5518. <varlistentry>
  5519. <term>Throws:</term>
  5520. <listitem>
  5521. <para>
  5522. Timeout-related exceptions.
  5523. </para>
  5524. </listitem>
  5525. </varlistentry>
  5526. </variablelist>
  5527. <para>
  5528. <bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_for_bridgehead">
  5529. <phrase id="recursive_timed_mutex_try_lock_for"/>
  5530. <link linkend="recursive_timed_mutex_try_lock_for">Templated
  5531. member function <code>try_lock_for</code>()</link>
  5532. </bridgehead>
  5533. </para>
  5534. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  5535. <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
  5536. </programlisting>
  5537. <variablelist>
  5538. <title></title>
  5539. <varlistentry>
  5540. <term>Effects:</term>
  5541. <listitem>
  5542. <para>
  5543. Attempt to obtain ownership for the current fiber. Blocks until ownership
  5544. can be obtained, or the specified time is reached. If the specified
  5545. time has already passed, behaves as <link linkend="recursive_timed_mutex_try_lock"><code>recursive_timed_mutex::try_lock()</code></link>.
  5546. </para>
  5547. </listitem>
  5548. </varlistentry>
  5549. <varlistentry>
  5550. <term>Returns:</term>
  5551. <listitem>
  5552. <para>
  5553. <code><phrase role="keyword">true</phrase></code> if ownership was
  5554. obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
  5555. otherwise.
  5556. </para>
  5557. </listitem>
  5558. </varlistentry>
  5559. <varlistentry>
  5560. <term>Throws:</term>
  5561. <listitem>
  5562. <para>
  5563. Timeout-related exceptions.
  5564. </para>
  5565. </listitem>
  5566. </varlistentry>
  5567. </variablelist>
  5568. </section>
  5569. <section id="fiber.synchronization.conditions">
  5570. <title><link linkend="fiber.synchronization.conditions">Condition Variables</link></title>
  5571. <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h0">
  5572. <phrase id="fiber.synchronization.conditions.synopsis"/><link linkend="fiber.synchronization.conditions.synopsis">Synopsis</link>
  5573. </bridgehead>
  5574. <programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">cv_status</phrase><phrase role="special">;</phrase> <phrase role="special">{</phrase>
  5575. <phrase role="identifier">no_timeout</phrase><phrase role="special">,</phrase>
  5576. <phrase role="identifier">timeout</phrase>
  5577. <phrase role="special">};</phrase>
  5578. <phrase role="keyword">class</phrase> <phrase role="identifier">condition_variable</phrase><phrase role="special">;</phrase>
  5579. <phrase role="keyword">class</phrase> <phrase role="identifier">condition_variable_any</phrase><phrase role="special">;</phrase>
  5580. </programlisting>
  5581. <para>
  5582. The class <link linkend="class_condition_variable"><code>condition_variable</code></link> provides a mechanism
  5583. for a fiber to wait for notification from another fiber. When the fiber awakens
  5584. from the wait, then it checks to see if the appropriate condition is now
  5585. true, and continues if so. If the condition is not true, then the fiber calls
  5586. <code><phrase role="identifier">wait</phrase></code> again to resume waiting.
  5587. In the simplest case, this condition is just a boolean variable:
  5588. </para>
  5589. <programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase> <phrase role="identifier">cond</phrase><phrase role="special">;</phrase>
  5590. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">;</phrase>
  5591. <phrase role="keyword">bool</phrase> <phrase role="identifier">data_ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
  5592. <phrase role="keyword">void</phrase> <phrase role="identifier">process_data</phrase><phrase role="special">();</phrase>
  5593. <phrase role="keyword">void</phrase> <phrase role="identifier">wait_for_data_to_process</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  5594. <phrase role="special">{</phrase>
  5595. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">);</phrase>
  5596. <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">data_ready</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  5597. <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
  5598. <phrase role="special">}</phrase>
  5599. <phrase role="special">}</phrase> <phrase role="comment">// release lk</phrase>
  5600. <phrase role="identifier">process_data</phrase><phrase role="special">();</phrase>
  5601. <phrase role="special">}</phrase>
  5602. </programlisting>
  5603. <para>
  5604. Notice that the <code><phrase role="identifier">lk</phrase></code> is passed
  5605. to <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>: <code><phrase role="identifier">wait</phrase><phrase
  5606. role="special">()</phrase></code> will atomically add the fiber to the set
  5607. of fibers waiting on the condition variable, and unlock the <link linkend="class_mutex"><code>mutex</code></link>.
  5608. When the fiber is awakened, the <code><phrase role="identifier">mutex</phrase></code>
  5609. will be locked again before the call to <code><phrase role="identifier">wait</phrase><phrase
  5610. role="special">()</phrase></code> returns. This allows other fibers to acquire
  5611. the <code><phrase role="identifier">mutex</phrase></code> in order to update
  5612. the shared data, and ensures that the data associated with the condition
  5613. is correctly synchronized.
  5614. </para>
  5615. <para>
  5616. <code><phrase role="identifier">wait_for_data_to_process</phrase><phrase
  5617. role="special">()</phrase></code> could equivalently be written:
  5618. </para>
  5619. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait_for_data_to_process</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  5620. <phrase role="special">{</phrase>
  5621. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">);</phrase>
  5622. <phrase role="comment">// make condition_variable::wait() perform the loop</phrase>
  5623. <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">data_ready</phrase><phrase role="special">;</phrase> <phrase role="special">});</phrase>
  5624. <phrase role="special">}</phrase> <phrase role="comment">// release lk</phrase>
  5625. <phrase role="identifier">process_data</phrase><phrase role="special">();</phrase>
  5626. <phrase role="special">}</phrase>
  5627. </programlisting>
  5628. <para>
  5629. In the meantime, another fiber sets <code><phrase role="identifier">data_ready</phrase></code>
  5630. to <code><phrase role="keyword">true</phrase></code>, and then calls either
  5631. <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link> or <link linkend="condition_variable_notify_all"><code>condition_variable::notify_all()</code></link> on
  5632. the <link linkend="class_condition_variable"><code>condition_variable</code></link> <code><phrase role="identifier">cond</phrase></code>
  5633. to wake one waiting fiber or all the waiting fibers respectively.
  5634. </para>
  5635. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">retrieve_data</phrase><phrase role="special">();</phrase>
  5636. <phrase role="keyword">void</phrase> <phrase role="identifier">prepare_data</phrase><phrase role="special">();</phrase>
  5637. <phrase role="keyword">void</phrase> <phrase role="identifier">prepare_data_for_processing</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  5638. <phrase role="identifier">retrieve_data</phrase><phrase role="special">();</phrase>
  5639. <phrase role="identifier">prepare_data</phrase><phrase role="special">();</phrase>
  5640. <phrase role="special">{</phrase>
  5641. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">);</phrase>
  5642. <phrase role="identifier">data_ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
  5643. <phrase role="special">}</phrase>
  5644. <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase>
  5645. <phrase role="special">}</phrase>
  5646. </programlisting>
  5647. <para>
  5648. Note that the same <link linkend="class_mutex"><code>mutex</code></link> is locked before the shared data is updated,
  5649. but that the <code><phrase role="identifier">mutex</phrase></code> does not
  5650. have to be locked across the call to <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link>.
  5651. </para>
  5652. <para>
  5653. Locking is important because the synchronization objects provided by <emphasis
  5654. role="bold">Boost.Fiber</emphasis> can be used to synchronize fibers running
  5655. on different threads.
  5656. </para>
  5657. <para>
  5658. <emphasis role="bold">Boost.Fiber</emphasis> provides both <link linkend="class_condition_variable"><code>condition_variable</code></link> and
  5659. <link linkend="class_condition_variable_any"><code>condition_variable_any</code></link>. <code><phrase role="identifier">boost</phrase><phrase
  5660. role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
  5661. role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code>
  5662. can only wait on <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
  5663. role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase></code></ulink><code><phrase
  5664. role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase
  5665. role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
  5666. role="special">::</phrase></code><link linkend="class_mutex"><code>mutex</code></link><code> <phrase role="special">&gt;</phrase></code>
  5667. while <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  5668. role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase
  5669. role="identifier">condition_variable_any</phrase></code> can wait on user-defined
  5670. lock types.
  5671. </para>
  5672. <anchor id="condition_variable_spurious_wakeups"/>
  5673. <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h1">
  5674. <phrase id="fiber.synchronization.conditions.no_spurious_wakeups"/><link
  5675. linkend="fiber.synchronization.conditions.no_spurious_wakeups">No Spurious
  5676. Wakeups</link>
  5677. </bridgehead>
  5678. <para>
  5679. Neither <link linkend="class_condition_variable"><code>condition_variable</code></link> nor <link linkend="class_condition_variable_any"><code>condition_variable_any</code></link> are
  5680. subject to spurious wakeup: <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link> can
  5681. only wake up when <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link> or
  5682. <link linkend="condition_variable_notify_all"><code>condition_variable::notify_all()</code></link> is called. Even
  5683. so, it is prudent to use one of the <code><phrase role="identifier">wait</phrase><phrase
  5684. role="special">(</phrase> <phrase role="identifier">lock</phrase><phrase
  5685. role="special">,</phrase> <phrase role="identifier">predicate</phrase> <phrase
  5686. role="special">)</phrase></code> overloads.
  5687. </para>
  5688. <para>
  5689. Consider a set of consumer fibers processing items from a <ulink url="http://en.cppreference.com/w/cpp/container/queue"><code><phrase
  5690. role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">queue</phrase></code></ulink>.
  5691. The queue is continually populated by a set of producer fibers.
  5692. </para>
  5693. <para>
  5694. The consumer fibers might reasonably wait on a <code><phrase role="identifier">condition_variable</phrase></code>
  5695. as long as the queue remains <ulink url="http://en.cppreference.com/w/cpp/container/queue/empty"><code><phrase
  5696. role="identifier">empty</phrase><phrase role="special">()</phrase></code></ulink>.
  5697. </para>
  5698. <para>
  5699. Because producer fibers might <ulink url="http://en.cppreference.com/w/cpp/container/queue/push"><code><phrase
  5700. role="identifier">push</phrase><phrase role="special">()</phrase></code></ulink>
  5701. items to the queue in bursts, they call <link linkend="condition_variable_notify_all"><code>condition_variable::notify_all()</code></link> rather
  5702. than <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link>.
  5703. </para>
  5704. <para>
  5705. But a given consumer fiber might well wake up from <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link> and
  5706. find the queue <code><phrase role="identifier">empty</phrase><phrase role="special">()</phrase></code>,
  5707. because other consumer fibers might already have processed all pending items.
  5708. </para>
  5709. <para>
  5710. (See also <link linkend="spurious_wakeup">spurious wakeup</link>.)
  5711. </para>
  5712. <anchor id="class_cv_status"/>
  5713. <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h2">
  5714. <phrase id="fiber.synchronization.conditions.enumeration__code__phrase_role__identifier__cv_status__phrase___code_"/><link
  5715. linkend="fiber.synchronization.conditions.enumeration__code__phrase_role__identifier__cv_status__phrase___code_">Enumeration
  5716. <code><phrase role="identifier">cv_status</phrase></code></link>
  5717. </bridgehead>
  5718. <para>
  5719. A timed wait operation might return because of timeout or not.
  5720. </para>
  5721. <programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">cv_status</phrase> <phrase role="special">{</phrase>
  5722. <phrase role="identifier">no_timeout</phrase><phrase role="special">,</phrase>
  5723. <phrase role="identifier">timeout</phrase>
  5724. <phrase role="special">};</phrase>
  5725. </programlisting>
  5726. <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h3">
  5727. <phrase id="fiber.synchronization.conditions._code__phrase_role__identifier__no_timeout__phrase___code_"/><link
  5728. linkend="fiber.synchronization.conditions._code__phrase_role__identifier__no_timeout__phrase___code_"><code><phrase
  5729. role="identifier">no_timeout</phrase></code></link>
  5730. </bridgehead>
  5731. <variablelist>
  5732. <title></title>
  5733. <varlistentry>
  5734. <term>Effects:</term>
  5735. <listitem>
  5736. <para>
  5737. The condition variable was awakened with <code><phrase role="identifier">notify_one</phrase></code>
  5738. or <code><phrase role="identifier">notify_all</phrase></code>.
  5739. </para>
  5740. </listitem>
  5741. </varlistentry>
  5742. </variablelist>
  5743. <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h4">
  5744. <phrase id="fiber.synchronization.conditions._code__phrase_role__identifier__timeout__phrase___code_"/><link
  5745. linkend="fiber.synchronization.conditions._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase
  5746. role="identifier">timeout</phrase></code></link>
  5747. </bridgehead>
  5748. <variablelist>
  5749. <title></title>
  5750. <varlistentry>
  5751. <term>Effects:</term>
  5752. <listitem>
  5753. <para>
  5754. The condition variable was awakened by timeout.
  5755. </para>
  5756. </listitem>
  5757. </varlistentry>
  5758. </variablelist>
  5759. <para>
  5760. <bridgehead renderas="sect4" id="class_condition_variable_any_bridgehead">
  5761. <phrase id="class_condition_variable_any"/>
  5762. <link linkend="class_condition_variable_any">Class
  5763. <code>condition_variable_any</code></link>
  5764. </bridgehead>
  5765. </para>
  5766. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">condition_variable</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  5767. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  5768. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  5769. <phrase role="keyword">class</phrase> condition_variable_any <phrase role="special">{</phrase>
  5770. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  5771. condition_variable_any<phrase role="special">();</phrase>
  5772. <phrase role="special">~</phrase>condition_variable_any<phrase role="special">();</phrase>
  5773. condition_variable_any<phrase role="special">(</phrase> condition_variable_any <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  5774. condition_variable_any <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> condition_variable_any <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  5775. <phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  5776. <phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  5777. template&lt; typename LockType &gt;
  5778. void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;);</phrase>
  5779. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
  5780. <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
  5781. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  5782. <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase>
  5783. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;);</phrase>
  5784. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
  5785. <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase>
  5786. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase>
  5787. <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
  5788. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  5789. <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase>
  5790. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;);</phrase>
  5791. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
  5792. <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase>
  5793. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase>
  5794. <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
  5795. <phrase role="special">};</phrase>
  5796. <phrase role="special">}}</phrase>
  5797. </programlisting>
  5798. <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h5">
  5799. <phrase id="fiber.synchronization.conditions.constructor"/><link linkend="fiber.synchronization.conditions.constructor">Constructor</link>
  5800. </bridgehead>
  5801. <programlisting>condition_variable_any<phrase role="special">()</phrase>
  5802. </programlisting>
  5803. <variablelist>
  5804. <title></title>
  5805. <varlistentry>
  5806. <term>Effects:</term>
  5807. <listitem>
  5808. <para>
  5809. Creates the object.
  5810. </para>
  5811. </listitem>
  5812. </varlistentry>
  5813. <varlistentry>
  5814. <term>Throws:</term>
  5815. <listitem>
  5816. <para>
  5817. Nothing.
  5818. </para>
  5819. </listitem>
  5820. </varlistentry>
  5821. </variablelist>
  5822. <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h6">
  5823. <phrase id="fiber.synchronization.conditions.destructor"/><link linkend="fiber.synchronization.conditions.destructor">Destructor</link>
  5824. </bridgehead>
  5825. <programlisting><phrase role="special">~</phrase>condition_variable_any<phrase role="special">()</phrase>
  5826. </programlisting>
  5827. <variablelist>
  5828. <title></title>
  5829. <varlistentry>
  5830. <term>Precondition:</term>
  5831. <listitem>
  5832. <para>
  5833. All fibers waiting on <code><phrase role="special">*</phrase><phrase
  5834. role="keyword">this</phrase></code> have been notified by a call to
  5835. <code><phrase role="identifier">notify_one</phrase></code> or <code><phrase
  5836. role="identifier">notify_all</phrase></code> (though the respective
  5837. calls to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
  5838. role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
  5839. need not have returned).
  5840. </para>
  5841. </listitem>
  5842. </varlistentry>
  5843. <varlistentry>
  5844. <term>Effects:</term>
  5845. <listitem>
  5846. <para>
  5847. Destroys the object.
  5848. </para>
  5849. </listitem>
  5850. </varlistentry>
  5851. </variablelist>
  5852. <para>
  5853. <bridgehead renderas="sect4" id="condition_variable_any_notify_one_bridgehead">
  5854. <phrase id="condition_variable_any_notify_one"/>
  5855. <link linkend="condition_variable_any_notify_one">Member
  5856. function <code>notify_one</code>()</link>
  5857. </bridgehead>
  5858. </para>
  5859. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  5860. </programlisting>
  5861. <variablelist>
  5862. <title></title>
  5863. <varlistentry>
  5864. <term>Effects:</term>
  5865. <listitem>
  5866. <para>
  5867. If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
  5868. waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  5869. in a call to <code><phrase role="identifier">wait</phrase></code>,
  5870. <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
  5871. role="identifier">wait_until</phrase></code>, unblocks one of those
  5872. fibers.
  5873. </para>
  5874. </listitem>
  5875. </varlistentry>
  5876. <varlistentry>
  5877. <term>Throws:</term>
  5878. <listitem>
  5879. <para>
  5880. Nothing.
  5881. </para>
  5882. </listitem>
  5883. </varlistentry>
  5884. <varlistentry>
  5885. <term>Note:</term>
  5886. <listitem>
  5887. <para>
  5888. It is arbitrary which waiting fiber is resumed.
  5889. </para>
  5890. </listitem>
  5891. </varlistentry>
  5892. </variablelist>
  5893. <para>
  5894. <bridgehead renderas="sect4" id="condition_variable_any_notify_all_bridgehead">
  5895. <phrase id="condition_variable_any_notify_all"/>
  5896. <link linkend="condition_variable_any_notify_all">Member
  5897. function <code>notify_all</code>()</link>
  5898. </bridgehead>
  5899. </para>
  5900. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  5901. </programlisting>
  5902. <variablelist>
  5903. <title></title>
  5904. <varlistentry>
  5905. <term>Effects:</term>
  5906. <listitem>
  5907. <para>
  5908. If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
  5909. waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  5910. in a call to <code><phrase role="identifier">wait</phrase></code>,
  5911. <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
  5912. role="identifier">wait_until</phrase></code>, unblocks all of those
  5913. fibers.
  5914. </para>
  5915. </listitem>
  5916. </varlistentry>
  5917. <varlistentry>
  5918. <term>Throws:</term>
  5919. <listitem>
  5920. <para>
  5921. Nothing.
  5922. </para>
  5923. </listitem>
  5924. </varlistentry>
  5925. <varlistentry>
  5926. <term>Note:</term>
  5927. <listitem>
  5928. <para>
  5929. This is why a waiting fiber must <emphasis>also</emphasis> check for
  5930. the desired program state using a mechanism external to the <code>condition_variable_any</code>,
  5931. and retry the wait until that state is reached. A fiber waiting on
  5932. a <code>condition_variable_any</code> might well wake up a number of times before
  5933. the desired state is reached.
  5934. </para>
  5935. </listitem>
  5936. </varlistentry>
  5937. </variablelist>
  5938. <para>
  5939. <bridgehead renderas="sect4" id="condition_variable_any_wait_bridgehead">
  5940. <phrase id="condition_variable_any_wait"/>
  5941. <link linkend="condition_variable_any_wait">Templated
  5942. member function <code>wait</code>()</link>
  5943. </bridgehead>
  5944. </para>
  5945. <programlisting>template&lt; typename LockType &gt;
  5946. void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
  5947. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
  5948. <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
  5949. </programlisting>
  5950. <variablelist>
  5951. <title></title>
  5952. <varlistentry>
  5953. <term>Precondition:</term>
  5954. <listitem>
  5955. <para>
  5956. <code><phrase role="identifier">lk</phrase></code> is locked by the
  5957. current fiber, and either no other fiber is currently waiting on <code><phrase
  5958. role="special">*</phrase><phrase role="keyword">this</phrase></code>,
  5959. or the execution of the <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock/mutex"><code><phrase
  5960. role="identifier">mutex</phrase><phrase role="special">()</phrase></code></ulink>
  5961. member function on the <code><phrase role="identifier">lk</phrase></code>
  5962. objects supplied in the calls to <code><phrase role="identifier">wait</phrase></code>
  5963. in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
  5964. role="keyword">this</phrase></code> would return the same value as
  5965. <code><phrase role="identifier">lk</phrase><phrase role="special">-&gt;</phrase><phrase
  5966. role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
  5967. for this call to <code><phrase role="identifier">wait</phrase></code>.
  5968. </para>
  5969. </listitem>
  5970. </varlistentry>
  5971. <varlistentry>
  5972. <term>Effects:</term>
  5973. <listitem>
  5974. <para>
  5975. Atomically call <code><phrase role="identifier">lk</phrase><phrase
  5976. role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
  5977. role="special">()</phrase></code> and blocks the current fiber. The
  5978. fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
  5979. role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
  5980. role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
  5981. role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
  5982. role="special">()</phrase></code>. When the fiber is unblocked (for
  5983. whatever reason), the lock is reacquired by invoking <code><phrase
  5984. role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
  5985. role="identifier">lock</phrase><phrase role="special">()</phrase></code>
  5986. before the call to <code><phrase role="identifier">wait</phrase></code>
  5987. returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
  5988. role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
  5989. role="special">()</phrase></code> if the function exits with an exception.
  5990. The member function accepting <code><phrase role="identifier">pred</phrase></code>
  5991. is shorthand for:
  5992. <programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  5993. <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
  5994. <phrase role="special">}</phrase>
  5995. </programlisting>
  5996. </para>
  5997. </listitem>
  5998. </varlistentry>
  5999. <varlistentry>
  6000. <term>Postcondition:</term>
  6001. <listitem>
  6002. <para>
  6003. <code><phrase role="identifier">lk</phrase></code> is locked by the
  6004. current fiber.
  6005. </para>
  6006. </listitem>
  6007. </varlistentry>
  6008. <varlistentry>
  6009. <term>Throws:</term>
  6010. <listitem>
  6011. <para>
  6012. <code><phrase role="identifier">fiber_error</phrase></code> if an error
  6013. occurs.
  6014. </para>
  6015. </listitem>
  6016. </varlistentry>
  6017. <varlistentry>
  6018. <term>Note:</term>
  6019. <listitem>
  6020. <para>
  6021. The Precondition is a bit dense. It merely states that all the fibers
  6022. concurrently calling <code><phrase role="identifier">wait</phrase></code>
  6023. on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  6024. must wait on <code><phrase role="identifier">lk</phrase></code> objects
  6025. governing the <emphasis>same</emphasis> <link linkend="class_mutex"><code>mutex</code></link>. Three distinct
  6026. objects are involved in any <code>condition_variable_any::wait()</code> call: the
  6027. <code>condition_variable_any</code> itself, the <code><phrase role="identifier">mutex</phrase></code>
  6028. coordinating access between fibers and a local lock object (e.g. <ulink
  6029. url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
  6030. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  6031. role="identifier">unique_lock</phrase></code></ulink>). In general,
  6032. you can partition the lifespan of a given <code>condition_variable_any</code> instance
  6033. into periods with one or more fibers waiting on it, separated by periods
  6034. when no fibers are waiting on it. When more than one fiber is waiting
  6035. on that <code>condition_variable_any</code>, all must pass lock objects referencing
  6036. the <emphasis>same</emphasis> <code><phrase role="identifier">mutex</phrase></code>
  6037. instance.
  6038. </para>
  6039. </listitem>
  6040. </varlistentry>
  6041. </variablelist>
  6042. <para>
  6043. <bridgehead renderas="sect4" id="condition_variable_any_wait_until_bridgehead">
  6044. <phrase id="condition_variable_any_wait_until"/>
  6045. <link linkend="condition_variable_any_wait_until">Templated
  6046. member function <code>wait_until</code>()</link>
  6047. </bridgehead>
  6048. </para>
  6049. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  6050. <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
  6051. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">);</phrase>
  6052. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
  6053. <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
  6054. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">,</phrase>
  6055. <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
  6056. </programlisting>
  6057. <variablelist>
  6058. <title></title>
  6059. <varlistentry>
  6060. <term>Precondition:</term>
  6061. <listitem>
  6062. <para>
  6063. <code><phrase role="identifier">lk</phrase></code> is locked by the
  6064. current fiber, and either no other fiber is currently waiting on <code><phrase
  6065. role="special">*</phrase><phrase role="keyword">this</phrase></code>,
  6066. or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
  6067. role="special">()</phrase></code> member function on the <code><phrase
  6068. role="identifier">lk</phrase></code> objects supplied in the calls
  6069. to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
  6070. role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
  6071. in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
  6072. role="keyword">this</phrase></code> would return the same value as
  6073. <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
  6074. role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
  6075. for this call to <code><phrase role="identifier">wait_until</phrase></code>.
  6076. </para>
  6077. </listitem>
  6078. </varlistentry>
  6079. <varlistentry>
  6080. <term>Effects:</term>
  6081. <listitem>
  6082. <para>
  6083. Atomically call <code><phrase role="identifier">lk</phrase><phrase
  6084. role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
  6085. role="special">()</phrase></code> and blocks the current fiber. The
  6086. fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
  6087. role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
  6088. role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
  6089. role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
  6090. role="special">()</phrase></code>, when the system time would be equal
  6091. to or later than the specified <code><phrase role="identifier">abs_time</phrase></code>.
  6092. When the fiber is unblocked (for whatever reason), the lock is reacquired
  6093. by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
  6094. role="identifier">lock</phrase><phrase role="special">()</phrase></code>
  6095. before the call to <code><phrase role="identifier">wait_until</phrase></code>
  6096. returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
  6097. role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
  6098. role="special">()</phrase></code> if the function exits with an exception.
  6099. The member function accepting <code><phrase role="identifier">pred</phrase></code>
  6100. is shorthand for:
  6101. <programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  6102. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase role="identifier">timeout</phrase> <phrase role="special">==</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase>
  6103. <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
  6104. <phrase role="special">}</phrase>
  6105. <phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
  6106. </programlisting>
  6107. That is, even if <code><phrase role="identifier">wait_until</phrase><phrase
  6108. role="special">()</phrase></code> times out, it can still return <code><phrase
  6109. role="keyword">true</phrase></code> if <code><phrase role="identifier">pred</phrase><phrase
  6110. role="special">()</phrase></code> returns <code><phrase role="keyword">true</phrase></code>
  6111. at that time.
  6112. </para>
  6113. </listitem>
  6114. </varlistentry>
  6115. <varlistentry>
  6116. <term>Postcondition:</term>
  6117. <listitem>
  6118. <para>
  6119. <code><phrase role="identifier">lk</phrase></code> is locked by the
  6120. current fiber.
  6121. </para>
  6122. </listitem>
  6123. </varlistentry>
  6124. <varlistentry>
  6125. <term>Throws:</term>
  6126. <listitem>
  6127. <para>
  6128. <code><phrase role="identifier">fiber_error</phrase></code> if an error
  6129. occurs or timeout-related exceptions.
  6130. </para>
  6131. </listitem>
  6132. </varlistentry>
  6133. <varlistentry>
  6134. <term>Returns:</term>
  6135. <listitem>
  6136. <para>
  6137. The overload without <code><phrase role="identifier">pred</phrase></code>
  6138. returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
  6139. role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
  6140. role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
  6141. or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
  6142. or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
  6143. role="identifier">timeout</phrase></code> if awakened because the system
  6144. time is past <code><phrase role="identifier">abs_time</phrase></code>.
  6145. </para>
  6146. </listitem>
  6147. </varlistentry>
  6148. <varlistentry>
  6149. <term>Returns:</term>
  6150. <listitem>
  6151. <para>
  6152. The overload accepting <code><phrase role="identifier">pred</phrase></code>
  6153. returns <code><phrase role="keyword">false</phrase></code> if the call
  6154. is returning because the time specified by <code><phrase role="identifier">abs_time</phrase></code>
  6155. was reached and the predicate returns <code><phrase role="keyword">false</phrase></code>,
  6156. <code><phrase role="keyword">true</phrase></code> otherwise.
  6157. </para>
  6158. </listitem>
  6159. </varlistentry>
  6160. <varlistentry>
  6161. <term>Note:</term>
  6162. <listitem>
  6163. <para>
  6164. See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_any_wait"><code>condition_variable_any::wait()</code></link>.
  6165. </para>
  6166. </listitem>
  6167. </varlistentry>
  6168. </variablelist>
  6169. <para>
  6170. <bridgehead renderas="sect4" id="condition_variable_any_wait_for_bridgehead">
  6171. <phrase id="condition_variable_any_wait_for"/>
  6172. <link linkend="condition_variable_any_wait_for">Templated
  6173. member function <code>wait_for</code>()</link>
  6174. </bridgehead>
  6175. </para>
  6176. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  6177. <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
  6178. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">);</phrase>
  6179. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
  6180. <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
  6181. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">,</phrase>
  6182. <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
  6183. </programlisting>
  6184. <variablelist>
  6185. <title></title>
  6186. <varlistentry>
  6187. <term>Precondition:</term>
  6188. <listitem>
  6189. <para>
  6190. <code><phrase role="identifier">lk</phrase></code> is locked by the
  6191. current fiber, and either no other fiber is currently waiting on <code><phrase
  6192. role="special">*</phrase><phrase role="keyword">this</phrase></code>,
  6193. or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
  6194. role="special">()</phrase></code> member function on the <code><phrase
  6195. role="identifier">lk</phrase></code> objects supplied in the calls
  6196. to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
  6197. role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
  6198. in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
  6199. role="keyword">this</phrase></code> would return the same value as
  6200. <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
  6201. role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
  6202. for this call to <code><phrase role="identifier">wait_for</phrase></code>.
  6203. </para>
  6204. </listitem>
  6205. </varlistentry>
  6206. <varlistentry>
  6207. <term>Effects:</term>
  6208. <listitem>
  6209. <para>
  6210. Atomically call <code><phrase role="identifier">lk</phrase><phrase
  6211. role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
  6212. role="special">()</phrase></code> and blocks the current fiber. The
  6213. fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
  6214. role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
  6215. role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
  6216. role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
  6217. role="special">()</phrase></code>, when a time interval equal to or
  6218. greater than the specified <code><phrase role="identifier">rel_time</phrase></code>
  6219. has elapsed. When the fiber is unblocked (for whatever reason), the
  6220. lock is reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
  6221. role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
  6222. role="special">()</phrase></code> before the call to <code><phrase
  6223. role="identifier">wait</phrase></code> returns. The lock is also reacquired
  6224. by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
  6225. role="identifier">lock</phrase><phrase role="special">()</phrase></code>
  6226. if the function exits with an exception. The <code><phrase role="identifier">wait_for</phrase><phrase
  6227. role="special">()</phrase></code> member function accepting <code><phrase
  6228. role="identifier">pred</phrase></code> is shorthand for:
  6229. <programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  6230. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase role="identifier">timeout</phrase> <phrase role="special">==</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  6231. <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
  6232. <phrase role="special">}</phrase>
  6233. <phrase role="special">}</phrase>
  6234. <phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
  6235. </programlisting>
  6236. (except of course that <code><phrase role="identifier">rel_time</phrase></code>
  6237. is adjusted for each iteration). The point is that, even if <code><phrase
  6238. role="identifier">wait_for</phrase><phrase role="special">()</phrase></code>
  6239. times out, it can still return <code><phrase role="keyword">true</phrase></code>
  6240. if <code><phrase role="identifier">pred</phrase><phrase role="special">()</phrase></code>
  6241. returns <code><phrase role="keyword">true</phrase></code> at that time.
  6242. </para>
  6243. </listitem>
  6244. </varlistentry>
  6245. <varlistentry>
  6246. <term>Postcondition:</term>
  6247. <listitem>
  6248. <para>
  6249. <code><phrase role="identifier">lk</phrase></code> is locked by the
  6250. current fiber.
  6251. </para>
  6252. </listitem>
  6253. </varlistentry>
  6254. <varlistentry>
  6255. <term>Throws:</term>
  6256. <listitem>
  6257. <para>
  6258. <code><phrase role="identifier">fiber_error</phrase></code> if an error
  6259. occurs or timeout-related exceptions.
  6260. </para>
  6261. </listitem>
  6262. </varlistentry>
  6263. <varlistentry>
  6264. <term>Returns:</term>
  6265. <listitem>
  6266. <para>
  6267. The overload without <code><phrase role="identifier">pred</phrase></code>
  6268. returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
  6269. role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
  6270. role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
  6271. or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
  6272. or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
  6273. role="identifier">timeout</phrase></code> if awakened because at least
  6274. <code><phrase role="identifier">rel_time</phrase></code> has elapsed.
  6275. </para>
  6276. </listitem>
  6277. </varlistentry>
  6278. <varlistentry>
  6279. <term>Returns:</term>
  6280. <listitem>
  6281. <para>
  6282. The overload accepting <code><phrase role="identifier">pred</phrase></code>
  6283. returns <code><phrase role="keyword">false</phrase></code> if the call
  6284. is returning because at least <code><phrase role="identifier">rel_time</phrase></code>
  6285. has elapsed and the predicate returns <code><phrase role="keyword">false</phrase></code>,
  6286. <code><phrase role="keyword">true</phrase></code> otherwise.
  6287. </para>
  6288. </listitem>
  6289. </varlistentry>
  6290. <varlistentry>
  6291. <term>Note:</term>
  6292. <listitem>
  6293. <para>
  6294. See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_any_wait"><code>condition_variable_any::wait()</code></link>.
  6295. </para>
  6296. </listitem>
  6297. </varlistentry>
  6298. </variablelist>
  6299. <para>
  6300. <bridgehead renderas="sect4" id="class_condition_variable_bridgehead">
  6301. <phrase id="class_condition_variable"/>
  6302. <link linkend="class_condition_variable">Class
  6303. <code>condition_variable</code></link>
  6304. </bridgehead>
  6305. </para>
  6306. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">condition_variable</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  6307. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  6308. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  6309. <phrase role="keyword">class</phrase> condition_variable <phrase role="special">{</phrase>
  6310. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  6311. condition_variable<phrase role="special">();</phrase>
  6312. <phrase role="special">~</phrase>condition_variable<phrase role="special">();</phrase>
  6313. condition_variable<phrase role="special">(</phrase> condition_variable <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  6314. condition_variable <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> condition_variable <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  6315. <phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  6316. <phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  6317. void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;);</phrase>
  6318. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
  6319. <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
  6320. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  6321. <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;,</phrase>
  6322. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;);</phrase>
  6323. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
  6324. <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;,</phrase>
  6325. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase>
  6326. <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
  6327. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  6328. <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;,</phrase>
  6329. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;);</phrase>
  6330. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
  6331. <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;,</phrase>
  6332. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase>
  6333. <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
  6334. <phrase role="special">};</phrase>
  6335. <phrase role="special">}}</phrase>
  6336. </programlisting>
  6337. <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h7">
  6338. <phrase id="fiber.synchronization.conditions.constructor0"/><link linkend="fiber.synchronization.conditions.constructor0">Constructor</link>
  6339. </bridgehead>
  6340. <programlisting>condition_variable<phrase role="special">()</phrase>
  6341. </programlisting>
  6342. <variablelist>
  6343. <title></title>
  6344. <varlistentry>
  6345. <term>Effects:</term>
  6346. <listitem>
  6347. <para>
  6348. Creates the object.
  6349. </para>
  6350. </listitem>
  6351. </varlistentry>
  6352. <varlistentry>
  6353. <term>Throws:</term>
  6354. <listitem>
  6355. <para>
  6356. Nothing.
  6357. </para>
  6358. </listitem>
  6359. </varlistentry>
  6360. </variablelist>
  6361. <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h8">
  6362. <phrase id="fiber.synchronization.conditions.destructor0"/><link linkend="fiber.synchronization.conditions.destructor0">Destructor</link>
  6363. </bridgehead>
  6364. <programlisting><phrase role="special">~</phrase>condition_variable<phrase role="special">()</phrase>
  6365. </programlisting>
  6366. <variablelist>
  6367. <title></title>
  6368. <varlistentry>
  6369. <term>Precondition:</term>
  6370. <listitem>
  6371. <para>
  6372. All fibers waiting on <code><phrase role="special">*</phrase><phrase
  6373. role="keyword">this</phrase></code> have been notified by a call to
  6374. <code><phrase role="identifier">notify_one</phrase></code> or <code><phrase
  6375. role="identifier">notify_all</phrase></code> (though the respective
  6376. calls to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
  6377. role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
  6378. need not have returned).
  6379. </para>
  6380. </listitem>
  6381. </varlistentry>
  6382. <varlistentry>
  6383. <term>Effects:</term>
  6384. <listitem>
  6385. <para>
  6386. Destroys the object.
  6387. </para>
  6388. </listitem>
  6389. </varlistentry>
  6390. </variablelist>
  6391. <para>
  6392. <bridgehead renderas="sect4" id="condition_variable_notify_one_bridgehead">
  6393. <phrase id="condition_variable_notify_one"/>
  6394. <link linkend="condition_variable_notify_one">Member
  6395. function <code>notify_one</code>()</link>
  6396. </bridgehead>
  6397. </para>
  6398. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  6399. </programlisting>
  6400. <variablelist>
  6401. <title></title>
  6402. <varlistentry>
  6403. <term>Effects:</term>
  6404. <listitem>
  6405. <para>
  6406. If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
  6407. waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  6408. in a call to <code><phrase role="identifier">wait</phrase></code>,
  6409. <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
  6410. role="identifier">wait_until</phrase></code>, unblocks one of those
  6411. fibers.
  6412. </para>
  6413. </listitem>
  6414. </varlistentry>
  6415. <varlistentry>
  6416. <term>Throws:</term>
  6417. <listitem>
  6418. <para>
  6419. Nothing.
  6420. </para>
  6421. </listitem>
  6422. </varlistentry>
  6423. <varlistentry>
  6424. <term>Note:</term>
  6425. <listitem>
  6426. <para>
  6427. It is arbitrary which waiting fiber is resumed.
  6428. </para>
  6429. </listitem>
  6430. </varlistentry>
  6431. </variablelist>
  6432. <para>
  6433. <bridgehead renderas="sect4" id="condition_variable_notify_all_bridgehead">
  6434. <phrase id="condition_variable_notify_all"/>
  6435. <link linkend="condition_variable_notify_all">Member
  6436. function <code>notify_all</code>()</link>
  6437. </bridgehead>
  6438. </para>
  6439. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  6440. </programlisting>
  6441. <variablelist>
  6442. <title></title>
  6443. <varlistentry>
  6444. <term>Effects:</term>
  6445. <listitem>
  6446. <para>
  6447. If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
  6448. waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  6449. in a call to <code><phrase role="identifier">wait</phrase></code>,
  6450. <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
  6451. role="identifier">wait_until</phrase></code>, unblocks all of those
  6452. fibers.
  6453. </para>
  6454. </listitem>
  6455. </varlistentry>
  6456. <varlistentry>
  6457. <term>Throws:</term>
  6458. <listitem>
  6459. <para>
  6460. Nothing.
  6461. </para>
  6462. </listitem>
  6463. </varlistentry>
  6464. <varlistentry>
  6465. <term>Note:</term>
  6466. <listitem>
  6467. <para>
  6468. This is why a waiting fiber must <emphasis>also</emphasis> check for
  6469. the desired program state using a mechanism external to the <code>condition_variable</code>,
  6470. and retry the wait until that state is reached. A fiber waiting on
  6471. a <code>condition_variable</code> might well wake up a number of times before the
  6472. desired state is reached.
  6473. </para>
  6474. </listitem>
  6475. </varlistentry>
  6476. </variablelist>
  6477. <para>
  6478. <bridgehead renderas="sect4" id="condition_variable_wait_bridgehead">
  6479. <phrase id="condition_variable_wait"/>
  6480. <link linkend="condition_variable_wait">Templated
  6481. member function <code>wait</code>()</link>
  6482. </bridgehead>
  6483. </para>
  6484. <programlisting>void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
  6485. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
  6486. <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
  6487. </programlisting>
  6488. <variablelist>
  6489. <title></title>
  6490. <varlistentry>
  6491. <term>Precondition:</term>
  6492. <listitem>
  6493. <para>
  6494. <code><phrase role="identifier">lk</phrase></code> is locked by the
  6495. current fiber, and either no other fiber is currently waiting on <code><phrase
  6496. role="special">*</phrase><phrase role="keyword">this</phrase></code>,
  6497. or the execution of the <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock/mutex"><code><phrase
  6498. role="identifier">mutex</phrase><phrase role="special">()</phrase></code></ulink>
  6499. member function on the <code><phrase role="identifier">lk</phrase></code>
  6500. objects supplied in the calls to <code><phrase role="identifier">wait</phrase></code>
  6501. in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
  6502. role="keyword">this</phrase></code> would return the same value as
  6503. <code><phrase role="identifier">lk</phrase><phrase role="special">-&gt;</phrase><phrase
  6504. role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
  6505. for this call to <code><phrase role="identifier">wait</phrase></code>.
  6506. </para>
  6507. </listitem>
  6508. </varlistentry>
  6509. <varlistentry>
  6510. <term>Effects:</term>
  6511. <listitem>
  6512. <para>
  6513. Atomically call <code><phrase role="identifier">lk</phrase><phrase
  6514. role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
  6515. role="special">()</phrase></code> and blocks the current fiber. The
  6516. fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
  6517. role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
  6518. role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
  6519. role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
  6520. role="special">()</phrase></code>. When the fiber is unblocked (for
  6521. whatever reason), the lock is reacquired by invoking <code><phrase
  6522. role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
  6523. role="identifier">lock</phrase><phrase role="special">()</phrase></code>
  6524. before the call to <code><phrase role="identifier">wait</phrase></code>
  6525. returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
  6526. role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
  6527. role="special">()</phrase></code> if the function exits with an exception.
  6528. The member function accepting <code><phrase role="identifier">pred</phrase></code>
  6529. is shorthand for:
  6530. <programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  6531. <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
  6532. <phrase role="special">}</phrase>
  6533. </programlisting>
  6534. </para>
  6535. </listitem>
  6536. </varlistentry>
  6537. <varlistentry>
  6538. <term>Postcondition:</term>
  6539. <listitem>
  6540. <para>
  6541. <code><phrase role="identifier">lk</phrase></code> is locked by the
  6542. current fiber.
  6543. </para>
  6544. </listitem>
  6545. </varlistentry>
  6546. <varlistentry>
  6547. <term>Throws:</term>
  6548. <listitem>
  6549. <para>
  6550. <code><phrase role="identifier">fiber_error</phrase></code> if an error
  6551. occurs.
  6552. </para>
  6553. </listitem>
  6554. </varlistentry>
  6555. <varlistentry>
  6556. <term>Note:</term>
  6557. <listitem>
  6558. <para>
  6559. The Precondition is a bit dense. It merely states that all the fibers
  6560. concurrently calling <code><phrase role="identifier">wait</phrase></code>
  6561. on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  6562. must wait on <code><phrase role="identifier">lk</phrase></code> objects
  6563. governing the <emphasis>same</emphasis> <link linkend="class_mutex"><code>mutex</code></link>. Three distinct
  6564. objects are involved in any <code>condition_variable::wait()</code> call: the <code>condition_variable</code> itself,
  6565. the <code><phrase role="identifier">mutex</phrase></code> coordinating
  6566. access between fibers and a local lock object (e.g. <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
  6567. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  6568. role="identifier">unique_lock</phrase></code></ulink>). In general,
  6569. you can partition the lifespan of a given <code>condition_variable</code> instance
  6570. into periods with one or more fibers waiting on it, separated by periods
  6571. when no fibers are waiting on it. When more than one fiber is waiting
  6572. on that <code>condition_variable</code>, all must pass lock objects referencing
  6573. the <emphasis>same</emphasis> <code><phrase role="identifier">mutex</phrase></code>
  6574. instance.
  6575. </para>
  6576. </listitem>
  6577. </varlistentry>
  6578. </variablelist>
  6579. <para>
  6580. <bridgehead renderas="sect4" id="condition_variable_wait_until_bridgehead">
  6581. <phrase id="condition_variable_wait_until"/>
  6582. <link linkend="condition_variable_wait_until">Templated
  6583. member function <code>wait_until</code>()</link>
  6584. </bridgehead>
  6585. </para>
  6586. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  6587. <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
  6588. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">);</phrase>
  6589. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
  6590. <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
  6591. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">,</phrase>
  6592. <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
  6593. </programlisting>
  6594. <variablelist>
  6595. <title></title>
  6596. <varlistentry>
  6597. <term>Precondition:</term>
  6598. <listitem>
  6599. <para>
  6600. <code><phrase role="identifier">lk</phrase></code> is locked by the
  6601. current fiber, and either no other fiber is currently waiting on <code><phrase
  6602. role="special">*</phrase><phrase role="keyword">this</phrase></code>,
  6603. or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
  6604. role="special">()</phrase></code> member function on the <code><phrase
  6605. role="identifier">lk</phrase></code> objects supplied in the calls
  6606. to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
  6607. role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
  6608. in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
  6609. role="keyword">this</phrase></code> would return the same value as
  6610. <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
  6611. role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
  6612. for this call to <code><phrase role="identifier">wait_until</phrase></code>.
  6613. </para>
  6614. </listitem>
  6615. </varlistentry>
  6616. <varlistentry>
  6617. <term>Effects:</term>
  6618. <listitem>
  6619. <para>
  6620. Atomically call <code><phrase role="identifier">lk</phrase><phrase
  6621. role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
  6622. role="special">()</phrase></code> and blocks the current fiber. The
  6623. fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
  6624. role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
  6625. role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
  6626. role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
  6627. role="special">()</phrase></code>, when the system time would be equal
  6628. to or later than the specified <code><phrase role="identifier">abs_time</phrase></code>.
  6629. When the fiber is unblocked (for whatever reason), the lock is reacquired
  6630. by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
  6631. role="identifier">lock</phrase><phrase role="special">()</phrase></code>
  6632. before the call to <code><phrase role="identifier">wait_until</phrase></code>
  6633. returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
  6634. role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
  6635. role="special">()</phrase></code> if the function exits with an exception.
  6636. The member function accepting <code><phrase role="identifier">pred</phrase></code>
  6637. is shorthand for:
  6638. <programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  6639. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase role="identifier">timeout</phrase> <phrase role="special">==</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase>
  6640. <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
  6641. <phrase role="special">}</phrase>
  6642. <phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
  6643. </programlisting>
  6644. That is, even if <code><phrase role="identifier">wait_until</phrase><phrase
  6645. role="special">()</phrase></code> times out, it can still return <code><phrase
  6646. role="keyword">true</phrase></code> if <code><phrase role="identifier">pred</phrase><phrase
  6647. role="special">()</phrase></code> returns <code><phrase role="keyword">true</phrase></code>
  6648. at that time.
  6649. </para>
  6650. </listitem>
  6651. </varlistentry>
  6652. <varlistentry>
  6653. <term>Postcondition:</term>
  6654. <listitem>
  6655. <para>
  6656. <code><phrase role="identifier">lk</phrase></code> is locked by the
  6657. current fiber.
  6658. </para>
  6659. </listitem>
  6660. </varlistentry>
  6661. <varlistentry>
  6662. <term>Throws:</term>
  6663. <listitem>
  6664. <para>
  6665. <code><phrase role="identifier">fiber_error</phrase></code> if an error
  6666. occurs or timeout-related exceptions.
  6667. </para>
  6668. </listitem>
  6669. </varlistentry>
  6670. <varlistentry>
  6671. <term>Returns:</term>
  6672. <listitem>
  6673. <para>
  6674. The overload without <code><phrase role="identifier">pred</phrase></code>
  6675. returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
  6676. role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
  6677. role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
  6678. or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
  6679. or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
  6680. role="identifier">timeout</phrase></code> if awakened because the system
  6681. time is past <code><phrase role="identifier">abs_time</phrase></code>.
  6682. </para>
  6683. </listitem>
  6684. </varlistentry>
  6685. <varlistentry>
  6686. <term>Returns:</term>
  6687. <listitem>
  6688. <para>
  6689. The overload accepting <code><phrase role="identifier">pred</phrase></code>
  6690. returns <code><phrase role="keyword">false</phrase></code> if the call
  6691. is returning because the time specified by <code><phrase role="identifier">abs_time</phrase></code>
  6692. was reached and the predicate returns <code><phrase role="keyword">false</phrase></code>,
  6693. <code><phrase role="keyword">true</phrase></code> otherwise.
  6694. </para>
  6695. </listitem>
  6696. </varlistentry>
  6697. <varlistentry>
  6698. <term>Note:</term>
  6699. <listitem>
  6700. <para>
  6701. See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>.
  6702. </para>
  6703. </listitem>
  6704. </varlistentry>
  6705. </variablelist>
  6706. <para>
  6707. <bridgehead renderas="sect4" id="condition_variable_wait_for_bridgehead">
  6708. <phrase id="condition_variable_wait_for"/>
  6709. <link linkend="condition_variable_wait_for">Templated
  6710. member function <code>wait_for</code>()</link>
  6711. </bridgehead>
  6712. </para>
  6713. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  6714. <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
  6715. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">);</phrase>
  6716. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
  6717. <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
  6718. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">,</phrase>
  6719. <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
  6720. </programlisting>
  6721. <variablelist>
  6722. <title></title>
  6723. <varlistentry>
  6724. <term>Precondition:</term>
  6725. <listitem>
  6726. <para>
  6727. <code><phrase role="identifier">lk</phrase></code> is locked by the
  6728. current fiber, and either no other fiber is currently waiting on <code><phrase
  6729. role="special">*</phrase><phrase role="keyword">this</phrase></code>,
  6730. or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
  6731. role="special">()</phrase></code> member function on the <code><phrase
  6732. role="identifier">lk</phrase></code> objects supplied in the calls
  6733. to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
  6734. role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
  6735. in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
  6736. role="keyword">this</phrase></code> would return the same value as
  6737. <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
  6738. role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
  6739. for this call to <code><phrase role="identifier">wait_for</phrase></code>.
  6740. </para>
  6741. </listitem>
  6742. </varlistentry>
  6743. <varlistentry>
  6744. <term>Effects:</term>
  6745. <listitem>
  6746. <para>
  6747. Atomically call <code><phrase role="identifier">lk</phrase><phrase
  6748. role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
  6749. role="special">()</phrase></code> and blocks the current fiber. The
  6750. fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
  6751. role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
  6752. role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
  6753. role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
  6754. role="special">()</phrase></code>, when a time interval equal to or
  6755. greater than the specified <code><phrase role="identifier">rel_time</phrase></code>
  6756. has elapsed. When the fiber is unblocked (for whatever reason), the
  6757. lock is reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
  6758. role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
  6759. role="special">()</phrase></code> before the call to <code><phrase
  6760. role="identifier">wait</phrase></code> returns. The lock is also reacquired
  6761. by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
  6762. role="identifier">lock</phrase><phrase role="special">()</phrase></code>
  6763. if the function exits with an exception. The <code><phrase role="identifier">wait_for</phrase><phrase
  6764. role="special">()</phrase></code> member function accepting <code><phrase
  6765. role="identifier">pred</phrase></code> is shorthand for:
  6766. <programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  6767. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase role="identifier">timeout</phrase> <phrase role="special">==</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  6768. <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
  6769. <phrase role="special">}</phrase>
  6770. <phrase role="special">}</phrase>
  6771. <phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
  6772. </programlisting>
  6773. (except of course that <code><phrase role="identifier">rel_time</phrase></code>
  6774. is adjusted for each iteration). The point is that, even if <code><phrase
  6775. role="identifier">wait_for</phrase><phrase role="special">()</phrase></code>
  6776. times out, it can still return <code><phrase role="keyword">true</phrase></code>
  6777. if <code><phrase role="identifier">pred</phrase><phrase role="special">()</phrase></code>
  6778. returns <code><phrase role="keyword">true</phrase></code> at that time.
  6779. </para>
  6780. </listitem>
  6781. </varlistentry>
  6782. <varlistentry>
  6783. <term>Postcondition:</term>
  6784. <listitem>
  6785. <para>
  6786. <code><phrase role="identifier">lk</phrase></code> is locked by the
  6787. current fiber.
  6788. </para>
  6789. </listitem>
  6790. </varlistentry>
  6791. <varlistentry>
  6792. <term>Throws:</term>
  6793. <listitem>
  6794. <para>
  6795. <code><phrase role="identifier">fiber_error</phrase></code> if an error
  6796. occurs or timeout-related exceptions.
  6797. </para>
  6798. </listitem>
  6799. </varlistentry>
  6800. <varlistentry>
  6801. <term>Returns:</term>
  6802. <listitem>
  6803. <para>
  6804. The overload without <code><phrase role="identifier">pred</phrase></code>
  6805. returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
  6806. role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
  6807. role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
  6808. or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
  6809. or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
  6810. role="identifier">timeout</phrase></code> if awakened because at least
  6811. <code><phrase role="identifier">rel_time</phrase></code> has elapsed.
  6812. </para>
  6813. </listitem>
  6814. </varlistentry>
  6815. <varlistentry>
  6816. <term>Returns:</term>
  6817. <listitem>
  6818. <para>
  6819. The overload accepting <code><phrase role="identifier">pred</phrase></code>
  6820. returns <code><phrase role="keyword">false</phrase></code> if the call
  6821. is returning because at least <code><phrase role="identifier">rel_time</phrase></code>
  6822. has elapsed and the predicate returns <code><phrase role="keyword">false</phrase></code>,
  6823. <code><phrase role="keyword">true</phrase></code> otherwise.
  6824. </para>
  6825. </listitem>
  6826. </varlistentry>
  6827. <varlistentry>
  6828. <term>Note:</term>
  6829. <listitem>
  6830. <para>
  6831. See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>.
  6832. </para>
  6833. </listitem>
  6834. </varlistentry>
  6835. </variablelist>
  6836. </section>
  6837. <section id="fiber.synchronization.barriers">
  6838. <title><link linkend="fiber.synchronization.barriers">Barriers</link></title>
  6839. <para>
  6840. A barrier is a concept also known as a <emphasis>rendezvous</emphasis>, it
  6841. is a synchronization point between multiple contexts of execution (fibers).
  6842. The barrier is configured for a particular number of fibers (<code><phrase
  6843. role="identifier">n</phrase></code>), and as fibers reach the barrier they
  6844. must wait until all <code><phrase role="identifier">n</phrase></code> fibers
  6845. have arrived. Once the <code><phrase role="identifier">n</phrase></code>-th
  6846. fiber has reached the barrier, all the waiting fibers can proceed, and the
  6847. barrier is reset.
  6848. </para>
  6849. <para>
  6850. The fact that the barrier automatically resets is significant. Consider a
  6851. case in which you launch some number of fibers and want to wait only until
  6852. the first of them has completed. You might be tempted to use a <code><phrase
  6853. role="identifier">barrier</phrase><phrase role="special">(</phrase><phrase
  6854. role="number">2</phrase><phrase role="special">)</phrase></code> as the synchronization
  6855. mechanism, making each new fiber call its <link linkend="barrier_wait"><code>barrier::wait()</code></link> method,
  6856. then calling <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code>
  6857. in the launching fiber to wait until the first other fiber completes.
  6858. </para>
  6859. <para>
  6860. That will in fact unblock the launching fiber. The unfortunate part is that
  6861. it will continue blocking the <emphasis>remaining</emphasis> fibers.
  6862. </para>
  6863. <para>
  6864. Consider the following scenario:
  6865. </para>
  6866. <orderedlist>
  6867. <listitem>
  6868. <simpara>
  6869. Fiber <quote>main</quote> launches fibers A, B, C and D, then calls
  6870. <code><phrase role="identifier">barrier</phrase><phrase role="special">::</phrase><phrase
  6871. role="identifier">wait</phrase><phrase role="special">()</phrase></code>.
  6872. </simpara>
  6873. </listitem>
  6874. <listitem>
  6875. <simpara>
  6876. Fiber C finishes first and likewise calls <code><phrase role="identifier">barrier</phrase><phrase
  6877. role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
  6878. role="special">()</phrase></code>.
  6879. </simpara>
  6880. </listitem>
  6881. <listitem>
  6882. <simpara>
  6883. Fiber <quote>main</quote> is unblocked, as desired.
  6884. </simpara>
  6885. </listitem>
  6886. <listitem>
  6887. <simpara>
  6888. Fiber B calls <code><phrase role="identifier">barrier</phrase><phrase
  6889. role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
  6890. role="special">()</phrase></code>. Fiber B is <emphasis>blocked!</emphasis>
  6891. </simpara>
  6892. </listitem>
  6893. <listitem>
  6894. <simpara>
  6895. Fiber A calls <code><phrase role="identifier">barrier</phrase><phrase
  6896. role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
  6897. role="special">()</phrase></code>. Fibers A and B are unblocked.
  6898. </simpara>
  6899. </listitem>
  6900. <listitem>
  6901. <simpara>
  6902. Fiber D calls <code><phrase role="identifier">barrier</phrase><phrase
  6903. role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
  6904. role="special">()</phrase></code>. Fiber D is blocked indefinitely.
  6905. </simpara>
  6906. </listitem>
  6907. </orderedlist>
  6908. <para>
  6909. (See also <link linkend="wait_first_simple_section">when_any, simple completion</link>.)
  6910. </para>
  6911. <note>
  6912. <para>
  6913. It is unwise to tie the lifespan of a barrier to any one of its participating
  6914. fibers. Although conceptually all waiting fibers awaken <quote>simultaneously,</quote>
  6915. because of the nature of fibers, in practice they will awaken one by one
  6916. in indeterminate order.<footnote id="fiber.synchronization.barriers.f0">
  6917. <para>
  6918. The current implementation wakes fibers in FIFO order: the first to call
  6919. <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code>
  6920. wakes first, and so forth. But it is perilous to rely on the order in
  6921. which the various fibers will reach the <code><phrase role="identifier">wait</phrase><phrase
  6922. role="special">()</phrase></code> call.
  6923. </para>
  6924. </footnote> The rest of the waiting fibers will still be blocked in <code><phrase
  6925. role="identifier">wait</phrase><phrase role="special">()</phrase></code>,
  6926. which must, before returning, access data members in the barrier object.
  6927. </para>
  6928. </note>
  6929. <para>
  6930. <bridgehead renderas="sect4" id="class_barrier_bridgehead">
  6931. <phrase id="class_barrier"/>
  6932. <link linkend="class_barrier">Class <code>barrier</code></link>
  6933. </bridgehead>
  6934. </para>
  6935. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">barrier</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  6936. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  6937. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  6938. <phrase role="keyword">class</phrase> <phrase role="identifier">barrier</phrase> <phrase role="special">{</phrase>
  6939. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  6940. <phrase role="keyword">explicit</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">);</phrase>
  6941. <phrase role="identifier">barrier</phrase><phrase role="special">(</phrase> <phrase role="identifier">barrier</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  6942. <phrase role="identifier">barrier</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">barrier</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  6943. <phrase role="keyword">bool</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
  6944. <phrase role="special">};</phrase>
  6945. <phrase role="special">}}</phrase>
  6946. </programlisting>
  6947. <para>
  6948. Instances of <link linkend="class_barrier"><code>barrier</code></link> are not copyable or movable.
  6949. </para>
  6950. <bridgehead renderas="sect4" id="fiber.synchronization.barriers.h0">
  6951. <phrase id="fiber.synchronization.barriers.constructor"/><link linkend="fiber.synchronization.barriers.constructor">Constructor</link>
  6952. </bridgehead>
  6953. <programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">initial</phrase><phrase role="special">);</phrase>
  6954. </programlisting>
  6955. <variablelist>
  6956. <title></title>
  6957. <varlistentry>
  6958. <term>Effects:</term>
  6959. <listitem>
  6960. <para>
  6961. Construct a barrier for <code><phrase role="identifier">initial</phrase></code>
  6962. fibers.
  6963. </para>
  6964. </listitem>
  6965. </varlistentry>
  6966. <varlistentry>
  6967. <term>Throws:</term>
  6968. <listitem>
  6969. <para>
  6970. <code><phrase role="identifier">fiber_error</phrase></code>
  6971. </para>
  6972. </listitem>
  6973. </varlistentry>
  6974. <varlistentry>
  6975. <term>Error Conditions:</term>
  6976. <listitem>
  6977. <para>
  6978. <emphasis role="bold">invalid_argument</emphasis>: if <code><phrase
  6979. role="identifier">initial</phrase></code> is zero.
  6980. </para>
  6981. </listitem>
  6982. </varlistentry>
  6983. </variablelist>
  6984. <para>
  6985. <bridgehead renderas="sect4" id="barrier_wait_bridgehead">
  6986. <phrase id="barrier_wait"/>
  6987. <link linkend="barrier_wait">Member function <code>wait</code>()</link>
  6988. </bridgehead>
  6989. </para>
  6990. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
  6991. </programlisting>
  6992. <variablelist>
  6993. <title></title>
  6994. <varlistentry>
  6995. <term>Effects:</term>
  6996. <listitem>
  6997. <para>
  6998. Block until <code><phrase role="identifier">initial</phrase></code>
  6999. fibers have called <code><phrase role="identifier">wait</phrase></code>
  7000. on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
  7001. When the <code><phrase role="identifier">initial</phrase></code>-th
  7002. fiber calls <code><phrase role="identifier">wait</phrase></code>, all
  7003. waiting fibers are unblocked, and the barrier is reset.
  7004. </para>
  7005. </listitem>
  7006. </varlistentry>
  7007. <varlistentry>
  7008. <term>Returns:</term>
  7009. <listitem>
  7010. <para>
  7011. <code><phrase role="keyword">true</phrase></code> for exactly one fiber
  7012. from each batch of waiting fibers, <code><phrase role="keyword">false</phrase></code>
  7013. otherwise.
  7014. </para>
  7015. </listitem>
  7016. </varlistentry>
  7017. <varlistentry>
  7018. <term>Throws:</term>
  7019. <listitem>
  7020. <para>
  7021. <code><phrase role="identifier">fiber_error</phrase></code>
  7022. </para>
  7023. </listitem>
  7024. </varlistentry>
  7025. </variablelist>
  7026. </section>
  7027. <section id="fiber.synchronization.channels">
  7028. <title><link linkend="fiber.synchronization.channels">Channels</link></title>
  7029. <para>
  7030. A channel is a model to communicate and synchronize <code><phrase role="identifier">Threads</phrase>
  7031. <phrase role="identifier">of</phrase> <phrase role="identifier">Execution</phrase></code>
  7032. <footnote id="fiber.synchronization.channels.f0">
  7033. <para>
  7034. The smallest ordered sequence of instructions that can be managed independently
  7035. by a scheduler is called a <code><phrase role="identifier">Thread</phrase>
  7036. <phrase role="identifier">of</phrase> <phrase role="identifier">Execution</phrase></code>.
  7037. </para>
  7038. </footnote> via message passing.
  7039. </para>
  7040. <anchor id="class_channel_op_status"/>
  7041. <bridgehead renderas="sect4" id="fiber.synchronization.channels.h0">
  7042. <phrase id="fiber.synchronization.channels.enumeration__code__phrase_role__identifier__channel_op_status__phrase___code_"/><link
  7043. linkend="fiber.synchronization.channels.enumeration__code__phrase_role__identifier__channel_op_status__phrase___code_">Enumeration
  7044. <code><phrase role="identifier">channel_op_status</phrase></code></link>
  7045. </bridgehead>
  7046. <para>
  7047. channel operations return the state of the channel.
  7048. </para>
  7049. <programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">channel_op_status</phrase> <phrase role="special">{</phrase>
  7050. <phrase role="identifier">success</phrase><phrase role="special">,</phrase>
  7051. <phrase role="identifier">empty</phrase><phrase role="special">,</phrase>
  7052. <phrase role="identifier">full</phrase><phrase role="special">,</phrase>
  7053. <phrase role="identifier">closed</phrase><phrase role="special">,</phrase>
  7054. <phrase role="identifier">timeout</phrase>
  7055. <phrase role="special">};</phrase>
  7056. </programlisting>
  7057. <bridgehead renderas="sect4" id="fiber.synchronization.channels.h1">
  7058. <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__success__phrase___code_"/><link
  7059. linkend="fiber.synchronization.channels._code__phrase_role__identifier__success__phrase___code_"><code><phrase
  7060. role="identifier">success</phrase></code></link>
  7061. </bridgehead>
  7062. <variablelist>
  7063. <title></title>
  7064. <varlistentry>
  7065. <term>Effects:</term>
  7066. <listitem>
  7067. <para>
  7068. Operation was successful.
  7069. </para>
  7070. </listitem>
  7071. </varlistentry>
  7072. </variablelist>
  7073. <bridgehead renderas="sect4" id="fiber.synchronization.channels.h2">
  7074. <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__empty__phrase___code_"/><link
  7075. linkend="fiber.synchronization.channels._code__phrase_role__identifier__empty__phrase___code_"><code><phrase
  7076. role="identifier">empty</phrase></code></link>
  7077. </bridgehead>
  7078. <variablelist>
  7079. <title></title>
  7080. <varlistentry>
  7081. <term>Effects:</term>
  7082. <listitem>
  7083. <para>
  7084. channel is empty, operation failed.
  7085. </para>
  7086. </listitem>
  7087. </varlistentry>
  7088. </variablelist>
  7089. <bridgehead renderas="sect4" id="fiber.synchronization.channels.h3">
  7090. <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__full__phrase___code_"/><link
  7091. linkend="fiber.synchronization.channels._code__phrase_role__identifier__full__phrase___code_"><code><phrase
  7092. role="identifier">full</phrase></code></link>
  7093. </bridgehead>
  7094. <variablelist>
  7095. <title></title>
  7096. <varlistentry>
  7097. <term>Effects:</term>
  7098. <listitem>
  7099. <para>
  7100. channel is full, operation failed.
  7101. </para>
  7102. </listitem>
  7103. </varlistentry>
  7104. </variablelist>
  7105. <bridgehead renderas="sect4" id="fiber.synchronization.channels.h4">
  7106. <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__closed__phrase___code_"/><link
  7107. linkend="fiber.synchronization.channels._code__phrase_role__identifier__closed__phrase___code_"><code><phrase
  7108. role="identifier">closed</phrase></code></link>
  7109. </bridgehead>
  7110. <variablelist>
  7111. <title></title>
  7112. <varlistentry>
  7113. <term>Effects:</term>
  7114. <listitem>
  7115. <para>
  7116. channel is closed, operation failed.
  7117. </para>
  7118. </listitem>
  7119. </varlistentry>
  7120. </variablelist>
  7121. <bridgehead renderas="sect4" id="fiber.synchronization.channels.h5">
  7122. <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__timeout__phrase___code_"/><link
  7123. linkend="fiber.synchronization.channels._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase
  7124. role="identifier">timeout</phrase></code></link>
  7125. </bridgehead>
  7126. <variablelist>
  7127. <title></title>
  7128. <varlistentry>
  7129. <term>Effects:</term>
  7130. <listitem>
  7131. <para>
  7132. The operation did not become ready before specified timeout elapsed.
  7133. </para>
  7134. </listitem>
  7135. </varlistentry>
  7136. </variablelist>
  7137. <section id="fiber.synchronization.channels.buffered_channel">
  7138. <title><link linkend="fiber.synchronization.channels.buffered_channel">Buffered
  7139. Channel</link></title>
  7140. <para>
  7141. <emphasis role="bold">Boost.Fiber</emphasis> provides a bounded, buffered
  7142. channel (MPMC queue) suitable to synchonize fibers (running on same or
  7143. different threads) via asynchronouss message passing.
  7144. </para>
  7145. <programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
  7146. <phrase role="keyword">void</phrase> <phrase role="identifier">send</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7147. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="number">5</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7148. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">i</phrase><phrase role="special">);</phrase>
  7149. <phrase role="special">}</phrase>
  7150. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
  7151. <phrase role="special">}</phrase>
  7152. <phrase role="keyword">void</phrase> <phrase role="identifier">recv</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7153. <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase>
  7154. <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7155. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;received &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  7156. <phrase role="special">}</phrase>
  7157. <phrase role="special">}</phrase>
  7158. <phrase role="identifier">channel_t</phrase> <phrase role="identifier">chan</phrase><phrase role="special">{</phrase> <phrase role="number">2</phrase> <phrase role="special">};</phrase>
  7159. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f1</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">send</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
  7160. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f2</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">recv</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
  7161. <phrase role="identifier">f1</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  7162. <phrase role="identifier">f2</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  7163. </programlisting>
  7164. <para>
  7165. Class <code><phrase role="identifier">buffered_channel</phrase></code>
  7166. supports range-for syntax:
  7167. </para>
  7168. <programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
  7169. <phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7170. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase>
  7171. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase>
  7172. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">2</phrase><phrase role="special">);</phrase>
  7173. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">3</phrase><phrase role="special">);</phrase>
  7174. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">5</phrase><phrase role="special">);</phrase>
  7175. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">8</phrase><phrase role="special">);</phrase>
  7176. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">12</phrase><phrase role="special">);</phrase>
  7177. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
  7178. <phrase role="special">}</phrase>
  7179. <phrase role="keyword">void</phrase> <phrase role="identifier">bar</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7180. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">value</phrase> <phrase role="special">:</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7181. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">value</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; &quot;</phrase><phrase role="special">;</phrase>
  7182. <phrase role="special">}</phrase>
  7183. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  7184. <phrase role="special">}</phrase>
  7185. </programlisting>
  7186. <para>
  7187. <bridgehead renderas="sect4" id="class_buffered_channel_bridgehead">
  7188. <phrase id="class_buffered_channel"/>
  7189. <link linkend="class_buffered_channel">Template
  7190. <code>buffered_channel&lt;&gt;</code></link>
  7191. </bridgehead>
  7192. </para>
  7193. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  7194. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  7195. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  7196. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  7197. <phrase role="keyword">class</phrase> <phrase role="identifier">buffered_channel</phrase> <phrase role="special">{</phrase>
  7198. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  7199. <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
  7200. <phrase role="keyword">class</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">;</phrase>
  7201. <phrase role="keyword">explicit</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">capacity</phrase><phrase role="special">);</phrase>
  7202. <phrase role="identifier">buffered_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  7203. <phrase role="identifier">buffered_channel</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">buffered_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  7204. <phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  7205. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7206. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7207. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  7208. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase>
  7209. <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7210. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
  7211. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7212. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
  7213. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  7214. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
  7215. <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7216. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
  7217. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  7218. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
  7219. <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7220. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
  7221. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7222. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7223. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7224. <phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
  7225. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  7226. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
  7227. <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7228. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
  7229. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  7230. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
  7231. <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7232. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
  7233. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7234. <phrase role="special">};</phrase>
  7235. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  7236. <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">);</phrase>
  7237. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  7238. <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">);</phrase>
  7239. <phrase role="special">}}</phrase>
  7240. </programlisting>
  7241. <bridgehead renderas="sect5" id="fiber.synchronization.channels.buffered_channel.h0">
  7242. <phrase id="fiber.synchronization.channels.buffered_channel.constructor"/><link
  7243. linkend="fiber.synchronization.channels.buffered_channel.constructor">Constructor</link>
  7244. </bridgehead>
  7245. <programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">capacity</phrase><phrase role="special">);</phrase>
  7246. </programlisting>
  7247. <variablelist>
  7248. <title></title>
  7249. <varlistentry>
  7250. <term>Preconditions:</term>
  7251. <listitem>
  7252. <para>
  7253. <code><phrase role="number">2</phrase><phrase role="special">&lt;=</phrase><phrase
  7254. role="identifier">capacity</phrase> <phrase role="special">&amp;&amp;</phrase>
  7255. <phrase role="number">0</phrase><phrase role="special">==(</phrase><phrase
  7256. role="identifier">capacity</phrase> <phrase role="special">&amp;</phrase>
  7257. <phrase role="special">(</phrase><phrase role="identifier">capacity</phrase><phrase
  7258. role="special">-</phrase><phrase role="number">1</phrase><phrase
  7259. role="special">))</phrase></code>
  7260. </para>
  7261. </listitem>
  7262. </varlistentry>
  7263. <varlistentry>
  7264. <term>Effects:</term>
  7265. <listitem>
  7266. <para>
  7267. The constructor constructs an object of class <code><phrase role="identifier">buffered_channel</phrase></code>
  7268. with an internal buffer of size <code><phrase role="identifier">capacity</phrase></code>.
  7269. </para>
  7270. </listitem>
  7271. </varlistentry>
  7272. <varlistentry>
  7273. <term>Throws:</term>
  7274. <listitem>
  7275. <para>
  7276. <code><phrase role="identifier">fiber_error</phrase></code>
  7277. </para>
  7278. </listitem>
  7279. </varlistentry>
  7280. <varlistentry>
  7281. <term>Error Conditions:</term>
  7282. <listitem>
  7283. <para>
  7284. <emphasis role="bold">invalid_argument</emphasis>: if <code><phrase
  7285. role="number">0</phrase><phrase role="special">==</phrase><phrase
  7286. role="identifier">capacity</phrase> <phrase role="special">||</phrase>
  7287. <phrase role="number">0</phrase><phrase role="special">!=(</phrase><phrase
  7288. role="identifier">capacity</phrase> <phrase role="special">&amp;</phrase>
  7289. <phrase role="special">(</phrase><phrase role="identifier">capacity</phrase><phrase
  7290. role="special">-</phrase><phrase role="number">1</phrase><phrase
  7291. role="special">))</phrase></code>.
  7292. </para>
  7293. </listitem>
  7294. </varlistentry>
  7295. <varlistentry>
  7296. <term>Notes:</term>
  7297. <listitem>
  7298. <para>
  7299. A <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>,
  7300. <code><phrase role="identifier">push_wait_for</phrase><phrase role="special">()</phrase></code>
  7301. or <code><phrase role="identifier">push_wait_until</phrase><phrase
  7302. role="special">()</phrase></code> will not block until the number
  7303. of values in the channel becomes equal to <code><phrase role="identifier">capacity</phrase></code>.
  7304. The channel can hold only <code><phrase role="identifier">capacity</phrase>
  7305. <phrase role="special">-</phrase> <phrase role="number">1</phrase></code>
  7306. elements, otherwise it is considered to be full.
  7307. </para>
  7308. </listitem>
  7309. </varlistentry>
  7310. </variablelist>
  7311. <para>
  7312. <bridgehead renderas="sect4" id="buffered_channel_close_bridgehead">
  7313. <phrase id="buffered_channel_close"/>
  7314. <link linkend="buffered_channel_close">Member
  7315. function <code>close</code>()</link>
  7316. </bridgehead>
  7317. </para>
  7318. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  7319. </programlisting>
  7320. <variablelist>
  7321. <title></title>
  7322. <varlistentry>
  7323. <term>Effects:</term>
  7324. <listitem>
  7325. <para>
  7326. Deactivates the channel. No values can be put after calling <code><phrase
  7327. role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7328. role="identifier">close</phrase><phrase role="special">()</phrase></code>.
  7329. Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
  7330. role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase
  7331. role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
  7332. role="special">-&gt;</phrase><phrase role="identifier">pop_wait_for</phrase><phrase
  7333. role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
  7334. role="special">-&gt;</phrase><phrase role="identifier">pop_wait_until</phrase><phrase
  7335. role="special">()</phrase></code> will return <code><phrase role="identifier">closed</phrase></code>.
  7336. Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
  7337. role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase
  7338. role="special">()</phrase></code> will receive an exception.
  7339. </para>
  7340. </listitem>
  7341. </varlistentry>
  7342. <varlistentry>
  7343. <term>Throws:</term>
  7344. <listitem>
  7345. <para>
  7346. Nothing.
  7347. </para>
  7348. </listitem>
  7349. </varlistentry>
  7350. <varlistentry>
  7351. <term>Note:</term>
  7352. <listitem>
  7353. <para>
  7354. <code><phrase role="identifier">close</phrase><phrase role="special">()</phrase></code>
  7355. is like closing a pipe. It informs waiting consumers that no more
  7356. values will arrive.
  7357. </para>
  7358. </listitem>
  7359. </varlistentry>
  7360. </variablelist>
  7361. <para>
  7362. <bridgehead renderas="sect4" id="buffered_channel_push_bridgehead">
  7363. <phrase id="buffered_channel_push"/>
  7364. <link linkend="buffered_channel_push">Member
  7365. function <code>push</code>()</link>
  7366. </bridgehead>
  7367. </para>
  7368. <programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7369. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7370. </programlisting>
  7371. <variablelist>
  7372. <title></title>
  7373. <varlistentry>
  7374. <term>Effects:</term>
  7375. <listitem>
  7376. <para>
  7377. If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
  7378. Otherwise enqueues the value in the channel, wakes up a fiber blocked
  7379. on <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7380. role="identifier">pop</phrase><phrase role="special">()</phrase></code>,
  7381. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7382. role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>,
  7383. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7384. role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code>
  7385. or <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7386. role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code>
  7387. and returns <code><phrase role="identifier">success</phrase></code>.
  7388. If the channel is full, the fiber is blocked.
  7389. </para>
  7390. </listitem>
  7391. </varlistentry>
  7392. <varlistentry>
  7393. <term>Throws:</term>
  7394. <listitem>
  7395. <para>
  7396. Exceptions thrown by copy- or move-operations.
  7397. </para>
  7398. </listitem>
  7399. </varlistentry>
  7400. </variablelist>
  7401. <para>
  7402. <bridgehead renderas="sect4" id="buffered_channel_try_push_bridgehead">
  7403. <phrase id="buffered_channel_try_push"/>
  7404. <link linkend="buffered_channel_try_push">Member
  7405. function <code>try_push</code>()</link>
  7406. </bridgehead>
  7407. </para>
  7408. <programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7409. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7410. </programlisting>
  7411. <variablelist>
  7412. <title></title>
  7413. <varlistentry>
  7414. <term>Effects:</term>
  7415. <listitem>
  7416. <para>
  7417. If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
  7418. Otherwise enqueues the value in the channel, wakes up a fiber blocked
  7419. on <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7420. role="identifier">pop</phrase><phrase role="special">()</phrase></code>,
  7421. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7422. role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>,
  7423. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7424. role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code>
  7425. or <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7426. role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code>
  7427. and returns <code><phrase role="identifier">success</phrase></code>.
  7428. If the channel is full, it doesn't block and returns <code><phrase
  7429. role="identifier">full</phrase></code>.
  7430. </para>
  7431. </listitem>
  7432. </varlistentry>
  7433. <varlistentry>
  7434. <term>Throws:</term>
  7435. <listitem>
  7436. <para>
  7437. Exceptions thrown by copy- or move-operations.
  7438. </para>
  7439. </listitem>
  7440. </varlistentry>
  7441. </variablelist>
  7442. <para>
  7443. <bridgehead renderas="sect4" id="buffered_channel_pop_bridgehead">
  7444. <phrase id="buffered_channel_pop"/>
  7445. <link linkend="buffered_channel_pop">Member
  7446. function <code>pop</code>()</link>
  7447. </bridgehead>
  7448. </para>
  7449. <programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7450. </programlisting>
  7451. <variablelist>
  7452. <title></title>
  7453. <varlistentry>
  7454. <term>Effects:</term>
  7455. <listitem>
  7456. <para>
  7457. Dequeues a value from the channel. If the channel is empty, the fiber
  7458. gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
  7459. role="special">()</phrase></code>ed (return value <code><phrase role="identifier">success</phrase></code>
  7460. and <code><phrase role="identifier">va</phrase></code> contains dequeued
  7461. value) or the channel gets <code><phrase role="identifier">close</phrase><phrase
  7462. role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>).
  7463. </para>
  7464. </listitem>
  7465. </varlistentry>
  7466. <varlistentry>
  7467. <term>Throws:</term>
  7468. <listitem>
  7469. <para>
  7470. Exceptions thrown by copy- or move-operations.
  7471. </para>
  7472. </listitem>
  7473. </varlistentry>
  7474. </variablelist>
  7475. <para>
  7476. <bridgehead renderas="sect4" id="buffered_channel_value_pop_bridgehead">
  7477. <phrase id="buffered_channel_value_pop"/>
  7478. <link linkend="buffered_channel_value_pop">Member
  7479. function <code>value_pop</code>()</link>
  7480. </bridgehead>
  7481. </para>
  7482. <programlisting><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
  7483. </programlisting>
  7484. <variablelist>
  7485. <title></title>
  7486. <varlistentry>
  7487. <term>Effects:</term>
  7488. <listitem>
  7489. <para>
  7490. Dequeues a value from the channel. If the channel is empty, the fiber
  7491. gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
  7492. role="special">()</phrase></code>ed or the channel gets <code><phrase
  7493. role="identifier">close</phrase><phrase role="special">()</phrase></code>d
  7494. (which throws an exception).
  7495. </para>
  7496. </listitem>
  7497. </varlistentry>
  7498. <varlistentry>
  7499. <term>Throws:</term>
  7500. <listitem>
  7501. <para>
  7502. <code><phrase role="identifier">fiber_error</phrase></code> if <code><phrase
  7503. role="special">*</phrase><phrase role="keyword">this</phrase></code>
  7504. is closed or by copy- or move-operations.
  7505. </para>
  7506. </listitem>
  7507. </varlistentry>
  7508. <varlistentry>
  7509. <term>Error conditions:</term>
  7510. <listitem>
  7511. <para>
  7512. <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  7513. role="identifier">errc</phrase><phrase role="special">::</phrase><phrase
  7514. role="identifier">operation_not_permitted</phrase></code>
  7515. </para>
  7516. </listitem>
  7517. </varlistentry>
  7518. </variablelist>
  7519. <para>
  7520. <bridgehead renderas="sect4" id="buffered_channel_try_pop_bridgehead">
  7521. <phrase id="buffered_channel_try_pop"/>
  7522. <link linkend="buffered_channel_try_pop">Member
  7523. function <code>try_pop</code>()</link>
  7524. </bridgehead>
  7525. </para>
  7526. <programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7527. </programlisting>
  7528. <variablelist>
  7529. <title></title>
  7530. <varlistentry>
  7531. <term>Effects:</term>
  7532. <listitem>
  7533. <para>
  7534. If channel is empty, returns <code><phrase role="identifier">empty</phrase></code>.
  7535. If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
  7536. Otherwise it returns <code><phrase role="identifier">success</phrase></code>
  7537. and <code><phrase role="identifier">va</phrase></code> contains the
  7538. dequeued value.
  7539. </para>
  7540. </listitem>
  7541. </varlistentry>
  7542. <varlistentry>
  7543. <term>Throws:</term>
  7544. <listitem>
  7545. <para>
  7546. Exceptions thrown by copy- or move-operations.
  7547. </para>
  7548. </listitem>
  7549. </varlistentry>
  7550. </variablelist>
  7551. <para>
  7552. <bridgehead renderas="sect4" id="buffered_channel_pop_wait_for_bridgehead">
  7553. <phrase id="buffered_channel_pop_wait_for"/>
  7554. <link linkend="buffered_channel_pop_wait_for">Member
  7555. function <code>pop_wait_for</code>()</link>
  7556. </bridgehead>
  7557. </para>
  7558. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  7559. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
  7560. <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7561. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase>
  7562. </programlisting>
  7563. <variablelist>
  7564. <title></title>
  7565. <varlistentry>
  7566. <term>Effects:</term>
  7567. <listitem>
  7568. <para>
  7569. Accepts <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  7570. role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
  7571. role="identifier">duration</phrase></code> and internally computes
  7572. a timeout time as (system time + <code><phrase role="identifier">timeout_duration</phrase></code>).
  7573. If channel is not empty, immediately dequeues a value from the channel.
  7574. Otherwise the fiber gets suspended until at least one new item is
  7575. <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
  7576. (return value <code><phrase role="identifier">success</phrase></code>
  7577. and <code><phrase role="identifier">va</phrase></code> contains dequeued
  7578. value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
  7579. role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
  7580. or the system time reaches the computed timeout time (return value
  7581. <code><phrase role="identifier">timeout</phrase></code>).
  7582. </para>
  7583. </listitem>
  7584. </varlistentry>
  7585. <varlistentry>
  7586. <term>Throws:</term>
  7587. <listitem>
  7588. <para>
  7589. timeout-related exceptions or by copy- or move-operations.
  7590. </para>
  7591. </listitem>
  7592. </varlistentry>
  7593. </variablelist>
  7594. <para>
  7595. <bridgehead renderas="sect4" id="buffered_channel_pop_wait_until_bridgehead">
  7596. <phrase id="buffered_channel_pop_wait_until"/>
  7597. <link linkend="buffered_channel_pop_wait_until">Member
  7598. function <code>pop_wait_until</code>()</link>
  7599. </bridgehead>
  7600. </para>
  7601. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  7602. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
  7603. <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7604. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase>
  7605. </programlisting>
  7606. <variablelist>
  7607. <title></title>
  7608. <varlistentry>
  7609. <term>Effects:</term>
  7610. <listitem>
  7611. <para>
  7612. Accepts a <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  7613. role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
  7614. role="identifier">time_point</phrase><phrase role="special">&lt;</phrase>
  7615. <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase>
  7616. <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase></code>.
  7617. If channel is not empty, immediately dequeues a value from the channel.
  7618. Otherwise the fiber gets suspended until at least one new item is
  7619. <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
  7620. (return value <code><phrase role="identifier">success</phrase></code>
  7621. and <code><phrase role="identifier">va</phrase></code> contains dequeued
  7622. value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
  7623. role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
  7624. or the system time reaches the passed <code><phrase role="identifier">time_point</phrase></code>
  7625. (return value <code><phrase role="identifier">timeout</phrase></code>).
  7626. </para>
  7627. </listitem>
  7628. </varlistentry>
  7629. <varlistentry>
  7630. <term>Throws:</term>
  7631. <listitem>
  7632. <para>
  7633. timeout-related exceptions or by copy- or move-operations.
  7634. </para>
  7635. </listitem>
  7636. </varlistentry>
  7637. </variablelist>
  7638. <bridgehead renderas="sect5" id="fiber.synchronization.channels.buffered_channel.h1">
  7639. <phrase id="fiber.synchronization.channels.buffered_channel.non_member_function__code__phrase_role__identifier__begin__phrase__phrase_role__special_____phrase___phrase_role__identifier__buffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_"/><link
  7640. linkend="fiber.synchronization.channels.buffered_channel.non_member_function__code__phrase_role__identifier__begin__phrase__phrase_role__special_____phrase___phrase_role__identifier__buffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_">Non-member
  7641. function <code><phrase role="identifier">begin</phrase><phrase role="special">(</phrase>
  7642. <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase>
  7643. <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  7644. <phrase role="special">&amp;)</phrase></code></link>
  7645. </bridgehead>
  7646. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  7647. <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;);</phrase>
  7648. </programlisting>
  7649. <variablelist>
  7650. <title></title>
  7651. <varlistentry>
  7652. <term>Returns:</term>
  7653. <listitem>
  7654. <para>
  7655. Returns a range-iterator (input-iterator).
  7656. </para>
  7657. </listitem>
  7658. </varlistentry>
  7659. </variablelist>
  7660. <bridgehead renderas="sect5" id="fiber.synchronization.channels.buffered_channel.h2">
  7661. <phrase id="fiber.synchronization.channels.buffered_channel.non_member_function__code__phrase_role__identifier__end__phrase__phrase_role__special_____phrase___phrase_role__identifier__buffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_"/><link
  7662. linkend="fiber.synchronization.channels.buffered_channel.non_member_function__code__phrase_role__identifier__end__phrase__phrase_role__special_____phrase___phrase_role__identifier__buffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_">Non-member
  7663. function <code><phrase role="identifier">end</phrase><phrase role="special">(</phrase>
  7664. <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase>
  7665. <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  7666. <phrase role="special">&amp;)</phrase></code></link>
  7667. </bridgehead>
  7668. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  7669. <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;);</phrase>
  7670. </programlisting>
  7671. <variablelist>
  7672. <title></title>
  7673. <varlistentry>
  7674. <term>Returns:</term>
  7675. <listitem>
  7676. <para>
  7677. Returns an end range-iterator (input-iterator).
  7678. </para>
  7679. </listitem>
  7680. </varlistentry>
  7681. </variablelist>
  7682. </section>
  7683. <section id="fiber.synchronization.channels.unbuffered_channel">
  7684. <title><link linkend="fiber.synchronization.channels.unbuffered_channel">Unbuffered
  7685. Channel</link></title>
  7686. <para>
  7687. <emphasis role="bold">Boost.Fiber</emphasis> provides template <code><phrase
  7688. role="identifier">unbuffered_channel</phrase></code> suitable to synchonize
  7689. fibers (running on same or different threads) via synchronous message passing.
  7690. A fiber waiting to consume an value will block until the value is produced.
  7691. If a fiber attempts to send a value through an unbuffered channel and no
  7692. fiber is waiting to receive the value, the channel will block the sending
  7693. fiber.
  7694. </para>
  7695. <para>
  7696. The unbuffered channel acts as an <code><phrase role="identifier">rendezvous</phrase>
  7697. <phrase role="identifier">point</phrase></code>.
  7698. </para>
  7699. <programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
  7700. <phrase role="keyword">void</phrase> <phrase role="identifier">send</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7701. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="number">5</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7702. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">i</phrase><phrase role="special">);</phrase>
  7703. <phrase role="special">}</phrase>
  7704. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
  7705. <phrase role="special">}</phrase>
  7706. <phrase role="keyword">void</phrase> <phrase role="identifier">recv</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7707. <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase>
  7708. <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7709. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;received &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  7710. <phrase role="special">}</phrase>
  7711. <phrase role="special">}</phrase>
  7712. <phrase role="identifier">channel_t</phrase> <phrase role="identifier">chan</phrase><phrase role="special">{</phrase> <phrase role="number">1</phrase> <phrase role="special">};</phrase>
  7713. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f1</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">send</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
  7714. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f2</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">recv</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
  7715. <phrase role="identifier">f1</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  7716. <phrase role="identifier">f2</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  7717. </programlisting>
  7718. <para>
  7719. Range-for syntax is supported:
  7720. </para>
  7721. <programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
  7722. <phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7723. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase>
  7724. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase>
  7725. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">2</phrase><phrase role="special">);</phrase>
  7726. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">3</phrase><phrase role="special">);</phrase>
  7727. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">5</phrase><phrase role="special">);</phrase>
  7728. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">8</phrase><phrase role="special">);</phrase>
  7729. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">12</phrase><phrase role="special">);</phrase>
  7730. <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
  7731. <phrase role="special">}</phrase>
  7732. <phrase role="keyword">void</phrase> <phrase role="identifier">bar</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7733. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">value</phrase> <phrase role="special">:</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  7734. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">value</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; &quot;</phrase><phrase role="special">;</phrase>
  7735. <phrase role="special">}</phrase>
  7736. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  7737. <phrase role="special">}</phrase>
  7738. </programlisting>
  7739. <para>
  7740. <bridgehead renderas="sect4" id="class_unbuffered_channel_bridgehead">
  7741. <phrase id="class_unbuffered_channel"/>
  7742. <link linkend="class_unbuffered_channel">Template
  7743. <code>unbuffered_channel&lt;&gt;</code></link>
  7744. </bridgehead>
  7745. </para>
  7746. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">unbuffered_channel</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  7747. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  7748. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  7749. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  7750. <phrase role="keyword">class</phrase> <phrase role="identifier">unbuffered_channel</phrase> <phrase role="special">{</phrase>
  7751. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  7752. <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
  7753. <phrase role="keyword">class</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">;</phrase>
  7754. <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">();</phrase>
  7755. <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  7756. <phrase role="identifier">unbuffered_channel</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">unbuffered_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  7757. <phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  7758. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7759. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7760. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  7761. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase>
  7762. <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7763. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
  7764. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7765. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
  7766. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  7767. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
  7768. <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7769. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
  7770. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  7771. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
  7772. <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7773. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
  7774. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7775. <phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
  7776. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  7777. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
  7778. <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7779. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
  7780. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  7781. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
  7782. <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7783. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
  7784. <phrase role="special">};</phrase>
  7785. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  7786. <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">);</phrase>
  7787. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  7788. <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">);</phrase>
  7789. <phrase role="special">}}</phrase>
  7790. </programlisting>
  7791. <bridgehead renderas="sect5" id="fiber.synchronization.channels.unbuffered_channel.h0">
  7792. <phrase id="fiber.synchronization.channels.unbuffered_channel.constructor"/><link
  7793. linkend="fiber.synchronization.channels.unbuffered_channel.constructor">Constructor</link>
  7794. </bridgehead>
  7795. <programlisting><phrase role="identifier">unbuffered_channel</phrase><phrase role="special">();</phrase>
  7796. </programlisting>
  7797. <variablelist>
  7798. <title></title>
  7799. <varlistentry>
  7800. <term>Effects:</term>
  7801. <listitem>
  7802. <para>
  7803. The constructor constructs an object of class <code><phrase role="identifier">unbuffered_channel</phrase></code>.
  7804. </para>
  7805. </listitem>
  7806. </varlistentry>
  7807. </variablelist>
  7808. <para>
  7809. <bridgehead renderas="sect4" id="unbuffered_channel_close_bridgehead">
  7810. <phrase id="unbuffered_channel_close"/>
  7811. <link linkend="unbuffered_channel_close">Member
  7812. function <code>close</code>()</link>
  7813. </bridgehead>
  7814. </para>
  7815. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  7816. </programlisting>
  7817. <variablelist>
  7818. <title></title>
  7819. <varlistentry>
  7820. <term>Effects:</term>
  7821. <listitem>
  7822. <para>
  7823. Deactivates the channel. No values can be put after calling <code><phrase
  7824. role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7825. role="identifier">close</phrase><phrase role="special">()</phrase></code>.
  7826. Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
  7827. role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase
  7828. role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
  7829. role="special">-&gt;</phrase><phrase role="identifier">pop_wait_for</phrase><phrase
  7830. role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
  7831. role="special">-&gt;</phrase><phrase role="identifier">pop_wait_until</phrase><phrase
  7832. role="special">()</phrase></code> will return <code><phrase role="identifier">closed</phrase></code>.
  7833. Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
  7834. role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase
  7835. role="special">()</phrase></code> will receive an exception.
  7836. </para>
  7837. </listitem>
  7838. </varlistentry>
  7839. <varlistentry>
  7840. <term>Throws:</term>
  7841. <listitem>
  7842. <para>
  7843. Nothing.
  7844. </para>
  7845. </listitem>
  7846. </varlistentry>
  7847. <varlistentry>
  7848. <term>Note:</term>
  7849. <listitem>
  7850. <para>
  7851. <code><phrase role="identifier">close</phrase><phrase role="special">()</phrase></code>
  7852. is like closing a pipe. It informs waiting consumers that no more
  7853. values will arrive.
  7854. </para>
  7855. </listitem>
  7856. </varlistentry>
  7857. </variablelist>
  7858. <para>
  7859. <bridgehead renderas="sect4" id="unbuffered_channel_push_bridgehead">
  7860. <phrase id="unbuffered_channel_push"/>
  7861. <link linkend="unbuffered_channel_push">Member
  7862. function <code>push</code>()</link>
  7863. </bridgehead>
  7864. </para>
  7865. <programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7866. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7867. </programlisting>
  7868. <variablelist>
  7869. <title></title>
  7870. <varlistentry>
  7871. <term>Effects:</term>
  7872. <listitem>
  7873. <para>
  7874. If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
  7875. Otherwise enqueues the value in the channel, wakes up a fiber blocked
  7876. on <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7877. role="identifier">pop</phrase><phrase role="special">()</phrase></code>,
  7878. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7879. role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>,
  7880. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7881. role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code>
  7882. or <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  7883. role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code>
  7884. and returns <code><phrase role="identifier">success</phrase></code>.
  7885. </para>
  7886. </listitem>
  7887. </varlistentry>
  7888. <varlistentry>
  7889. <term>Throws:</term>
  7890. <listitem>
  7891. <para>
  7892. Exceptions thrown by copy- or move-operations.
  7893. </para>
  7894. </listitem>
  7895. </varlistentry>
  7896. </variablelist>
  7897. <para>
  7898. <bridgehead renderas="sect4" id="unbuffered_channel_pop_bridgehead">
  7899. <phrase id="unbuffered_channel_pop"/>
  7900. <link linkend="unbuffered_channel_pop">Member
  7901. function <code>pop</code>()</link>
  7902. </bridgehead>
  7903. </para>
  7904. <programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
  7905. </programlisting>
  7906. <variablelist>
  7907. <title></title>
  7908. <varlistentry>
  7909. <term>Effects:</term>
  7910. <listitem>
  7911. <para>
  7912. Dequeues a value from the channel. If the channel is empty, the fiber
  7913. gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
  7914. role="special">()</phrase></code>ed (return value <code><phrase role="identifier">success</phrase></code>
  7915. and <code><phrase role="identifier">va</phrase></code> contains dequeued
  7916. value) or the channel gets <code><phrase role="identifier">close</phrase><phrase
  7917. role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>).
  7918. </para>
  7919. </listitem>
  7920. </varlistentry>
  7921. <varlistentry>
  7922. <term>Throws:</term>
  7923. <listitem>
  7924. <para>
  7925. Exceptions thrown by copy- or move-operations.
  7926. </para>
  7927. </listitem>
  7928. </varlistentry>
  7929. </variablelist>
  7930. <para>
  7931. <bridgehead renderas="sect4" id="unbuffered_channel_value_pop_bridgehead">
  7932. <phrase id="unbuffered_channel_value_pop"/>
  7933. <link linkend="unbuffered_channel_value_pop">Member
  7934. function <code>value_pop</code>()</link>
  7935. </bridgehead>
  7936. </para>
  7937. <programlisting><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
  7938. </programlisting>
  7939. <variablelist>
  7940. <title></title>
  7941. <varlistentry>
  7942. <term>Effects:</term>
  7943. <listitem>
  7944. <para>
  7945. Dequeues a value from the channel. If the channel is empty, the fiber
  7946. gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
  7947. role="special">()</phrase></code>ed or the channel gets <code><phrase
  7948. role="identifier">close</phrase><phrase role="special">()</phrase></code>d
  7949. (which throws an exception).
  7950. </para>
  7951. </listitem>
  7952. </varlistentry>
  7953. <varlistentry>
  7954. <term>Throws:</term>
  7955. <listitem>
  7956. <para>
  7957. <code><phrase role="identifier">fiber_error</phrase></code> if <code><phrase
  7958. role="special">*</phrase><phrase role="keyword">this</phrase></code>
  7959. is closed or by copy- or move-operations.
  7960. </para>
  7961. </listitem>
  7962. </varlistentry>
  7963. <varlistentry>
  7964. <term>Error conditions:</term>
  7965. <listitem>
  7966. <para>
  7967. <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  7968. role="identifier">errc</phrase><phrase role="special">::</phrase><phrase
  7969. role="identifier">operation_not_permitted</phrase></code>
  7970. </para>
  7971. </listitem>
  7972. </varlistentry>
  7973. </variablelist>
  7974. <para>
  7975. <bridgehead renderas="sect4" id="unbuffered_channel_pop_wait_for_bridgehead">
  7976. <phrase id="unbuffered_channel_pop_wait_for"/>
  7977. <link linkend="unbuffered_channel_pop_wait_for">Member
  7978. function <code>pop_wait_for</code>()</link>
  7979. </bridgehead>
  7980. </para>
  7981. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  7982. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
  7983. <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  7984. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase>
  7985. </programlisting>
  7986. <variablelist>
  7987. <title></title>
  7988. <varlistentry>
  7989. <term>Effects:</term>
  7990. <listitem>
  7991. <para>
  7992. Accepts <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  7993. role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
  7994. role="identifier">duration</phrase></code> and internally computes
  7995. a timeout time as (system time + <code><phrase role="identifier">timeout_duration</phrase></code>).
  7996. If channel is not empty, immediately dequeues a value from the channel.
  7997. Otherwise the fiber gets suspended until at least one new item is
  7998. <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
  7999. (return value <code><phrase role="identifier">success</phrase></code>
  8000. and <code><phrase role="identifier">va</phrase></code> contains dequeued
  8001. value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
  8002. role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
  8003. or the system time reaches the computed timeout time (return value
  8004. <code><phrase role="identifier">timeout</phrase></code>).
  8005. </para>
  8006. </listitem>
  8007. </varlistentry>
  8008. <varlistentry>
  8009. <term>Throws:</term>
  8010. <listitem>
  8011. <para>
  8012. timeout-related exceptions or by copy- or move-operations.
  8013. </para>
  8014. </listitem>
  8015. </varlistentry>
  8016. </variablelist>
  8017. <para>
  8018. <bridgehead renderas="sect4" id="unbuffered_channel_pop_wait_until_bridgehead">
  8019. <phrase id="unbuffered_channel_pop_wait_until"/>
  8020. <link linkend="unbuffered_channel_pop_wait_until">Member
  8021. function <code>pop_wait_until</code>()</link>
  8022. </bridgehead>
  8023. </para>
  8024. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  8025. <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
  8026. <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
  8027. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase>
  8028. </programlisting>
  8029. <variablelist>
  8030. <title></title>
  8031. <varlistentry>
  8032. <term>Effects:</term>
  8033. <listitem>
  8034. <para>
  8035. Accepts a <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  8036. role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
  8037. role="identifier">time_point</phrase><phrase role="special">&lt;</phrase>
  8038. <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase>
  8039. <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase></code>.
  8040. If channel is not empty, immediately dequeues a value from the channel.
  8041. Otherwise the fiber gets suspended until at least one new item is
  8042. <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
  8043. (return value <code><phrase role="identifier">success</phrase></code>
  8044. and <code><phrase role="identifier">va</phrase></code> contains dequeued
  8045. value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
  8046. role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
  8047. or the system time reaches the passed <code><phrase role="identifier">time_point</phrase></code>
  8048. (return value <code><phrase role="identifier">timeout</phrase></code>).
  8049. </para>
  8050. </listitem>
  8051. </varlistentry>
  8052. <varlistentry>
  8053. <term>Throws:</term>
  8054. <listitem>
  8055. <para>
  8056. timeout-related exceptions or by copy- or move-operations.
  8057. </para>
  8058. </listitem>
  8059. </varlistentry>
  8060. </variablelist>
  8061. <bridgehead renderas="sect5" id="fiber.synchronization.channels.unbuffered_channel.h1">
  8062. <phrase id="fiber.synchronization.channels.unbuffered_channel.non_member_function__code__phrase_role__identifier__begin__phrase__phrase_role__special_____phrase___phrase_role__identifier__unbuffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_"/><link
  8063. linkend="fiber.synchronization.channels.unbuffered_channel.non_member_function__code__phrase_role__identifier__begin__phrase__phrase_role__special_____phrase___phrase_role__identifier__unbuffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_">Non-member
  8064. function <code><phrase role="identifier">begin</phrase><phrase role="special">(</phrase>
  8065. <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase>
  8066. <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  8067. <phrase role="special">&amp;)</phrase></code></link>
  8068. </bridgehead>
  8069. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  8070. <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;);</phrase>
  8071. </programlisting>
  8072. <variablelist>
  8073. <title></title>
  8074. <varlistentry>
  8075. <term>Returns:</term>
  8076. <listitem>
  8077. <para>
  8078. Returns a range-iterator (input-iterator).
  8079. </para>
  8080. </listitem>
  8081. </varlistentry>
  8082. </variablelist>
  8083. <bridgehead renderas="sect5" id="fiber.synchronization.channels.unbuffered_channel.h2">
  8084. <phrase id="fiber.synchronization.channels.unbuffered_channel.non_member_function__code__phrase_role__identifier__end__phrase__phrase_role__special_____phrase___phrase_role__identifier__unbuffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_"/><link
  8085. linkend="fiber.synchronization.channels.unbuffered_channel.non_member_function__code__phrase_role__identifier__end__phrase__phrase_role__special_____phrase___phrase_role__identifier__unbuffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_">Non-member
  8086. function <code><phrase role="identifier">end</phrase><phrase role="special">(</phrase>
  8087. <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase>
  8088. <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  8089. <phrase role="special">&amp;)</phrase></code></link>
  8090. </bridgehead>
  8091. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  8092. <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;);</phrase>
  8093. </programlisting>
  8094. <variablelist>
  8095. <title></title>
  8096. <varlistentry>
  8097. <term>Returns:</term>
  8098. <listitem>
  8099. <para>
  8100. Returns an end range-iterator (input-iterator).
  8101. </para>
  8102. </listitem>
  8103. </varlistentry>
  8104. </variablelist>
  8105. </section>
  8106. </section>
  8107. <section id="fiber.synchronization.futures">
  8108. <title><link linkend="fiber.synchronization.futures">Futures</link></title>
  8109. <bridgehead renderas="sect4" id="fiber.synchronization.futures.h0">
  8110. <phrase id="fiber.synchronization.futures.overview"/><link linkend="fiber.synchronization.futures.overview">Overview</link>
  8111. </bridgehead>
  8112. <para>
  8113. The futures library provides a means of handling asynchronous future values,
  8114. whether those values are generated by another fiber, or on a single fiber
  8115. in response to external stimuli, or on-demand.
  8116. </para>
  8117. <para>
  8118. This is done through the provision of four class templates: <link linkend="class_future"><code>future&lt;&gt;</code></link> and
  8119. <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> which are used to retrieve the asynchronous
  8120. results, and <link linkend="class_promise"><code>promise&lt;&gt;</code></link> and <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> which
  8121. are used to generate the asynchronous results.
  8122. </para>
  8123. <para>
  8124. An instance of <link linkend="class_future"><code>future&lt;&gt;</code></link> holds the one and only reference
  8125. to a result. Ownership can be transferred between instances using the move
  8126. constructor or move-assignment operator, but at most one instance holds a
  8127. reference to a given asynchronous result. When the result is ready, it is
  8128. returned from <link linkend="future_get"><code>future::get()</code></link> by rvalue-reference to allow the result
  8129. to be moved or copied as appropriate for the type.
  8130. </para>
  8131. <para>
  8132. On the other hand, many instances of <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> may
  8133. reference the same result. Instances can be freely copied and assigned, and
  8134. <link linkend="shared_future_get"><code>shared_future::get()</code></link>
  8135. returns a <code><phrase role="keyword">const</phrase></code>
  8136. reference so that multiple calls to <link linkend="shared_future_get"><code>shared_future::get()</code></link>
  8137. are
  8138. safe. You can move an instance of <link linkend="class_future"><code>future&lt;&gt;</code></link> into an instance
  8139. of <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link>, thus transferring ownership
  8140. of the associated asynchronous result, but not vice-versa.
  8141. </para>
  8142. <para>
  8143. <link linkend="fibers_async"><code>fibers::async()</code></link> is a simple way of running asynchronous tasks.
  8144. A call to <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code>
  8145. spawns a fiber and returns a <link linkend="class_future"><code>future&lt;&gt;</code></link> that will deliver
  8146. the result of the fiber function.
  8147. </para>
  8148. <bridgehead renderas="sect4" id="fiber.synchronization.futures.h1">
  8149. <phrase id="fiber.synchronization.futures.creating_asynchronous_values"/><link
  8150. linkend="fiber.synchronization.futures.creating_asynchronous_values">Creating
  8151. asynchronous values</link>
  8152. </bridgehead>
  8153. <para>
  8154. You can set the value in a future with either a <link linkend="class_promise"><code>promise&lt;&gt;</code></link> or
  8155. a <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link>. A <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> is
  8156. a callable object with <code><phrase role="keyword">void</phrase></code>
  8157. return that wraps a function or callable object returning the specified type.
  8158. When the <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> is invoked, it invokes the
  8159. contained function in turn, and populates a future with the contained function's
  8160. return value. This is an answer to the perennial question: <quote>How do
  8161. I return a value from a fiber?</quote> Package the function you wish to run
  8162. as a <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> and pass the packaged task to
  8163. the fiber constructor. The future retrieved from the packaged task can then
  8164. be used to obtain the return value. If the function throws an exception,
  8165. that is stored in the future in place of the return value.
  8166. </para>
  8167. <programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">calculate_the_answer_to_life_the_universe_and_everything</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  8168. <phrase role="keyword">return</phrase> <phrase role="number">42</phrase><phrase role="special">;</phrase>
  8169. <phrase role="special">}</phrase>
  8170. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">()&gt;</phrase> <phrase role="identifier">pt</phrase><phrase role="special">(</phrase><phrase role="identifier">calculate_the_answer_to_life_the_universe_and_everything</phrase><phrase role="special">);</phrase>
  8171. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">fi</phrase><phrase role="special">=</phrase><phrase role="identifier">pt</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
  8172. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">pt</phrase><phrase role="special">)).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> <phrase role="comment">// launch task on a fiber</phrase>
  8173. <phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase> <phrase role="comment">// wait for it to finish</phrase>
  8174. <phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">is_ready</phrase><phrase role="special">());</phrase>
  8175. <phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">has_value</phrase><phrase role="special">());</phrase>
  8176. <phrase role="identifier">assert</phrase><phrase role="special">(!</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">has_exception</phrase><phrase role="special">());</phrase>
  8177. <phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()==</phrase><phrase role="number">42</phrase><phrase role="special">);</phrase>
  8178. </programlisting>
  8179. <para>
  8180. A <link linkend="class_promise"><code>promise&lt;&gt;</code></link> is a bit more low level: it just provides explicit
  8181. functions to store a value or an exception in the associated future. A promise
  8182. can therefore be used where the value might come from more than one possible
  8183. source.
  8184. </para>
  8185. <programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">pi</phrase><phrase role="special">;</phrase>
  8186. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">fi</phrase><phrase role="special">;</phrase>
  8187. <phrase role="identifier">fi</phrase><phrase role="special">=</phrase><phrase role="identifier">pi</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
  8188. <phrase role="identifier">pi</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase><phrase role="number">42</phrase><phrase role="special">);</phrase>
  8189. <phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">is_ready</phrase><phrase role="special">());</phrase>
  8190. <phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">has_value</phrase><phrase role="special">());</phrase>
  8191. <phrase role="identifier">assert</phrase><phrase role="special">(!</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">has_exception</phrase><phrase role="special">());</phrase>
  8192. <phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()==</phrase><phrase role="number">42</phrase><phrase role="special">);</phrase>
  8193. </programlisting>
  8194. <section id="fiber.synchronization.futures.future">
  8195. <title><link linkend="fiber.synchronization.futures.future">Future</link></title>
  8196. <para>
  8197. A future provides a mechanism to access the result of an asynchronous operation.
  8198. </para>
  8199. <anchor id="shared_state"/>
  8200. <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h0">
  8201. <phrase id="fiber.synchronization.futures.future.shared_state"/><link linkend="fiber.synchronization.futures.future.shared_state">shared
  8202. state</link>
  8203. </bridgehead>
  8204. <para>
  8205. Behind a <link linkend="class_promise"><code>promise&lt;&gt;</code></link> and its <link linkend="class_future"><code>future&lt;&gt;</code></link> lies
  8206. an unspecified object called their <emphasis>shared state</emphasis>. The
  8207. shared state is what will actually hold the async result (or the exception).
  8208. </para>
  8209. <para>
  8210. The shared state is instantiated along with the <link linkend="class_promise"><code>promise&lt;&gt;</code></link>.
  8211. </para>
  8212. <para>
  8213. Aside from its originating <code><phrase role="identifier">promise</phrase><phrase
  8214. role="special">&lt;&gt;</phrase></code>, a <link linkend="class_future"><code>future&lt;&gt;</code></link> holds
  8215. a unique reference to a particular shared state. However, multiple <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> instances
  8216. can reference the same underlying shared state.
  8217. </para>
  8218. <para>
  8219. As <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> and <link linkend="fibers_async"><code>fibers::async()</code></link> are
  8220. implemented using <link linkend="class_promise"><code>promise&lt;&gt;</code></link>, discussions of shared state
  8221. apply to them as well.
  8222. </para>
  8223. <anchor id="class_future_status"/>
  8224. <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h1">
  8225. <phrase id="fiber.synchronization.futures.future.enumeration__code__phrase_role__identifier__future_status__phrase___code_"/><link
  8226. linkend="fiber.synchronization.futures.future.enumeration__code__phrase_role__identifier__future_status__phrase___code_">Enumeration
  8227. <code><phrase role="identifier">future_status</phrase></code></link>
  8228. </bridgehead>
  8229. <para>
  8230. Timed wait-operations (<link linkend="future_wait_for"><code>future::wait_for()</code></link> and <link linkend="future_wait_until"><code>future::wait_until()</code></link>)
  8231. return the state of the future.
  8232. </para>
  8233. <programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">future_status</phrase> <phrase role="special">{</phrase>
  8234. <phrase role="identifier">ready</phrase><phrase role="special">,</phrase>
  8235. <phrase role="identifier">timeout</phrase><phrase role="special">,</phrase>
  8236. <phrase role="identifier">deferred</phrase> <phrase role="comment">// not supported yet</phrase>
  8237. <phrase role="special">};</phrase>
  8238. </programlisting>
  8239. <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h2">
  8240. <phrase id="fiber.synchronization.futures.future._code__phrase_role__identifier__ready__phrase___code_"/><link
  8241. linkend="fiber.synchronization.futures.future._code__phrase_role__identifier__ready__phrase___code_"><code><phrase
  8242. role="identifier">ready</phrase></code></link>
  8243. </bridgehead>
  8244. <variablelist>
  8245. <title></title>
  8246. <varlistentry>
  8247. <term>Effects:</term>
  8248. <listitem>
  8249. <para>
  8250. The <link linkend="shared_state">shared state</link> is ready.
  8251. </para>
  8252. </listitem>
  8253. </varlistentry>
  8254. </variablelist>
  8255. <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h3">
  8256. <phrase id="fiber.synchronization.futures.future._code__phrase_role__identifier__timeout__phrase___code_"/><link
  8257. linkend="fiber.synchronization.futures.future._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase
  8258. role="identifier">timeout</phrase></code></link>
  8259. </bridgehead>
  8260. <variablelist>
  8261. <title></title>
  8262. <varlistentry>
  8263. <term>Effects:</term>
  8264. <listitem>
  8265. <para>
  8266. The <link linkend="shared_state">shared state</link> did not become
  8267. ready before timeout has passed.
  8268. </para>
  8269. </listitem>
  8270. </varlistentry>
  8271. </variablelist>
  8272. <note>
  8273. <para>
  8274. Deferred futures are not supported.
  8275. </para>
  8276. </note>
  8277. <para>
  8278. <bridgehead renderas="sect4" id="class_future_bridgehead">
  8279. <phrase id="class_future"/>
  8280. <link linkend="class_future">Template <code>future&lt;&gt;</code></link>
  8281. </bridgehead>
  8282. </para>
  8283. <para>
  8284. A <link linkend="class_future"><code>future&lt;&gt;</code></link> contains a <link linkend="shared_state">shared
  8285. state</link> which is not shared with any other future.
  8286. </para>
  8287. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">future</phrase><phrase role="special">/</phrase><phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  8288. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  8289. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  8290. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase>
  8291. <phrase role="keyword">class</phrase> <phrase role="identifier">future</phrase> <phrase role="special">{</phrase>
  8292. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  8293. <phrase role="identifier">future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8294. <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  8295. <phrase role="identifier">future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  8296. <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8297. <phrase role="identifier">future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8298. <phrase role="special">~</phrase><phrase role="identifier">future</phrase><phrase role="special">();</phrase>
  8299. <phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8300. <phrase role="identifier">shared_future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">share</phrase><phrase role="special">();</phrase>
  8301. <phrase role="identifier">R</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of generic future template</phrase>
  8302. <phrase role="identifier">R</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of future&lt; R &amp; &gt; template specialization</phrase>
  8303. <phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of future&lt; void &gt; template specialization</phrase>
  8304. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase>
  8305. <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
  8306. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  8307. <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase>
  8308. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
  8309. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  8310. <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase>
  8311. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
  8312. <phrase role="special">};</phrase>
  8313. <phrase role="special">}}</phrase>
  8314. </programlisting>
  8315. <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h4">
  8316. <phrase id="fiber.synchronization.futures.future.default_constructor"/><link
  8317. linkend="fiber.synchronization.futures.future.default_constructor">Default
  8318. constructor</link>
  8319. </bridgehead>
  8320. <programlisting><phrase role="identifier">future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8321. </programlisting>
  8322. <variablelist>
  8323. <title></title>
  8324. <varlistentry>
  8325. <term>Effects:</term>
  8326. <listitem>
  8327. <para>
  8328. Creates a future with no <link linkend="shared_state">shared state</link>.
  8329. After construction <code><phrase role="keyword">false</phrase> <phrase
  8330. role="special">==</phrase> <phrase role="identifier">valid</phrase><phrase
  8331. role="special">()</phrase></code>.
  8332. </para>
  8333. </listitem>
  8334. </varlistentry>
  8335. <varlistentry>
  8336. <term>Throws:</term>
  8337. <listitem>
  8338. <para>
  8339. Nothing.
  8340. </para>
  8341. </listitem>
  8342. </varlistentry>
  8343. </variablelist>
  8344. <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h5">
  8345. <phrase id="fiber.synchronization.futures.future.move_constructor"/><link
  8346. linkend="fiber.synchronization.futures.future.move_constructor">Move constructor</link>
  8347. </bridgehead>
  8348. <programlisting><phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8349. </programlisting>
  8350. <variablelist>
  8351. <title></title>
  8352. <varlistentry>
  8353. <term>Effects:</term>
  8354. <listitem>
  8355. <para>
  8356. Constructs a future with the <link linkend="shared_state">shared
  8357. state</link> of other. After construction <code><phrase role="keyword">false</phrase>
  8358. <phrase role="special">==</phrase> <phrase role="identifier">other</phrase><phrase
  8359. role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
  8360. role="special">()</phrase></code>.
  8361. </para>
  8362. </listitem>
  8363. </varlistentry>
  8364. <varlistentry>
  8365. <term>Throws:</term>
  8366. <listitem>
  8367. <para>
  8368. Nothing.
  8369. </para>
  8370. </listitem>
  8371. </varlistentry>
  8372. </variablelist>
  8373. <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h6">
  8374. <phrase id="fiber.synchronization.futures.future.destructor"/><link linkend="fiber.synchronization.futures.future.destructor">Destructor</link>
  8375. </bridgehead>
  8376. <programlisting><phrase role="special">~</phrase><phrase role="identifier">future</phrase><phrase role="special">();</phrase>
  8377. </programlisting>
  8378. <variablelist>
  8379. <title></title>
  8380. <varlistentry>
  8381. <term>Effects:</term>
  8382. <listitem>
  8383. <para>
  8384. Destroys the future; ownership is abandoned.
  8385. </para>
  8386. </listitem>
  8387. </varlistentry>
  8388. <varlistentry>
  8389. <term>Note:</term>
  8390. <listitem>
  8391. <para>
  8392. <code>~future()</code> does <emphasis>not</emphasis> block the calling fiber.
  8393. </para>
  8394. </listitem>
  8395. </varlistentry>
  8396. </variablelist>
  8397. <para>
  8398. Consider a sequence such as:
  8399. </para>
  8400. <orderedlist>
  8401. <listitem>
  8402. <simpara>
  8403. instantiate <link linkend="class_promise"><code>promise&lt;&gt;</code></link>
  8404. </simpara>
  8405. </listitem>
  8406. <listitem>
  8407. <simpara>
  8408. obtain its <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
  8409. via <link linkend="promise_get_future"><code>promise::get_future()</code></link>
  8410. </simpara>
  8411. </listitem>
  8412. <listitem>
  8413. <simpara>
  8414. launch <link linkend="class_fiber"><code>fiber</code></link>, capturing <code><phrase role="identifier">promise</phrase><phrase
  8415. role="special">&lt;&gt;</phrase></code>
  8416. </simpara>
  8417. </listitem>
  8418. <listitem>
  8419. <simpara>
  8420. destroy <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
  8421. </simpara>
  8422. </listitem>
  8423. <listitem>
  8424. <simpara>
  8425. call <link linkend="promise_set_value"><code>promise::set_value()</code></link>
  8426. </simpara>
  8427. </listitem>
  8428. </orderedlist>
  8429. <para>
  8430. The final <code><phrase role="identifier">set_value</phrase><phrase role="special">()</phrase></code>
  8431. call succeeds, but the value is silently discarded: no additional <code><phrase
  8432. role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
  8433. can be obtained from that <code><phrase role="identifier">promise</phrase><phrase
  8434. role="special">&lt;&gt;</phrase></code>.
  8435. </para>
  8436. <para>
  8437. <bridgehead renderas="sect4" id="future_operator_assign_bridgehead">
  8438. <phrase id="future_operator_assign"/>
  8439. <link linkend="future_operator_assign">Member
  8440. function <code>operator=</code>()</link>
  8441. </bridgehead>
  8442. </para>
  8443. <programlisting><phrase role="identifier">future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8444. </programlisting>
  8445. <variablelist>
  8446. <title></title>
  8447. <varlistentry>
  8448. <term>Effects:</term>
  8449. <listitem>
  8450. <para>
  8451. Moves the <link linkend="shared_state">shared state</link> of other
  8452. to <code><phrase role="keyword">this</phrase></code>. After the assignment,
  8453. <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
  8454. <phrase role="identifier">other</phrase><phrase role="special">.</phrase><phrase
  8455. role="identifier">valid</phrase><phrase role="special">()</phrase></code>.
  8456. </para>
  8457. </listitem>
  8458. </varlistentry>
  8459. <varlistentry>
  8460. <term>Throws:</term>
  8461. <listitem>
  8462. <para>
  8463. Nothing.
  8464. </para>
  8465. </listitem>
  8466. </varlistentry>
  8467. </variablelist>
  8468. <para>
  8469. <bridgehead renderas="sect4" id="future_valid_bridgehead">
  8470. <phrase id="future_valid"/>
  8471. <link linkend="future_valid">Member function <code>valid</code>()</link>
  8472. </bridgehead>
  8473. </para>
  8474. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8475. </programlisting>
  8476. <variablelist>
  8477. <title></title>
  8478. <varlistentry>
  8479. <term>Effects:</term>
  8480. <listitem>
  8481. <para>
  8482. Returns <code><phrase role="keyword">true</phrase></code> if future
  8483. contains a <link linkend="shared_state">shared state</link>.
  8484. </para>
  8485. </listitem>
  8486. </varlistentry>
  8487. <varlistentry>
  8488. <term>Throws:</term>
  8489. <listitem>
  8490. <para>
  8491. Nothing.
  8492. </para>
  8493. </listitem>
  8494. </varlistentry>
  8495. </variablelist>
  8496. <para>
  8497. <bridgehead renderas="sect4" id="future_share_bridgehead">
  8498. <phrase id="future_share"/>
  8499. <link linkend="future_share">Member function <code>share</code>()</link>
  8500. </bridgehead>
  8501. </para>
  8502. <programlisting><phrase role="identifier">shared_future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">share</phrase><phrase role="special">();</phrase>
  8503. </programlisting>
  8504. <variablelist>
  8505. <title></title>
  8506. <varlistentry>
  8507. <term>Effects:</term>
  8508. <listitem>
  8509. <para>
  8510. Move the state to a <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link>.
  8511. </para>
  8512. </listitem>
  8513. </varlistentry>
  8514. <varlistentry>
  8515. <term>Returns:</term>
  8516. <listitem>
  8517. <para>
  8518. a <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> containing the <link linkend="shared_state">shared
  8519. state</link> formerly belonging to <code><phrase role="special">*</phrase><phrase
  8520. role="keyword">this</phrase></code>.
  8521. </para>
  8522. </listitem>
  8523. </varlistentry>
  8524. <varlistentry>
  8525. <term>Postcondition:</term>
  8526. <listitem>
  8527. <para>
  8528. <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
  8529. <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
  8530. </para>
  8531. </listitem>
  8532. </varlistentry>
  8533. <varlistentry>
  8534. <term>Throws:</term>
  8535. <listitem>
  8536. <para>
  8537. <code><phrase role="identifier">future_error</phrase></code> with
  8538. error condition <code><phrase role="identifier">future_errc</phrase><phrase
  8539. role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
  8540. </para>
  8541. </listitem>
  8542. </varlistentry>
  8543. </variablelist>
  8544. <para>
  8545. <bridgehead renderas="sect4" id="future_get_bridgehead">
  8546. <phrase id="future_get"/>
  8547. <link linkend="future_get">Member function <code>get</code>()</link>
  8548. </bridgehead>
  8549. </para>
  8550. <programlisting><phrase role="identifier">R</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of generic future template</phrase>
  8551. <phrase role="identifier">R</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of future&lt; R &amp; &gt; template specialization</phrase>
  8552. <phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of future&lt; void &gt; template specialization</phrase>
  8553. </programlisting>
  8554. <variablelist>
  8555. <title></title>
  8556. <varlistentry>
  8557. <term>Precondition:</term>
  8558. <listitem>
  8559. <para>
  8560. <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
  8561. <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
  8562. </para>
  8563. </listitem>
  8564. </varlistentry>
  8565. <varlistentry>
  8566. <term>Returns:</term>
  8567. <listitem>
  8568. <para>
  8569. Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is
  8570. called. If <link linkend="promise_set_value"><code>promise::set_value()</code></link> is called, returns
  8571. the value. If <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is called,
  8572. throws the indicated exception.
  8573. </para>
  8574. </listitem>
  8575. </varlistentry>
  8576. <varlistentry>
  8577. <term>Postcondition:</term>
  8578. <listitem>
  8579. <para>
  8580. <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
  8581. <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
  8582. </para>
  8583. </listitem>
  8584. </varlistentry>
  8585. <varlistentry>
  8586. <term>Throws:</term>
  8587. <listitem>
  8588. <para>
  8589. <code><phrase role="identifier">future_error</phrase></code> with
  8590. error condition <code><phrase role="identifier">future_errc</phrase><phrase
  8591. role="special">::</phrase><phrase role="identifier">no_state</phrase></code>,
  8592. <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
  8593. role="identifier">broken_promise</phrase></code>. Any exception passed
  8594. to <code><phrase role="identifier">promise</phrase><phrase role="special">::</phrase><phrase
  8595. role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>.
  8596. </para>
  8597. </listitem>
  8598. </varlistentry>
  8599. </variablelist>
  8600. <para>
  8601. <bridgehead renderas="sect4" id="future_get_exception_ptr_bridgehead">
  8602. <phrase id="future_get_exception_ptr"/>
  8603. <link linkend="future_get_exception_ptr">Member
  8604. function <code>get_exception_ptr</code>()</link>
  8605. </bridgehead>
  8606. </para>
  8607. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase>
  8608. </programlisting>
  8609. <variablelist>
  8610. <title></title>
  8611. <varlistentry>
  8612. <term>Precondition:</term>
  8613. <listitem>
  8614. <para>
  8615. <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
  8616. <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
  8617. </para>
  8618. </listitem>
  8619. </varlistentry>
  8620. <varlistentry>
  8621. <term>Returns:</term>
  8622. <listitem>
  8623. <para>
  8624. Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is
  8625. called. If <code><phrase role="identifier">set_value</phrase><phrase
  8626. role="special">()</phrase></code> is called, returns a default-constructed
  8627. <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  8628. role="identifier">exception_ptr</phrase></code>. If <code><phrase
  8629. role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>
  8630. is called, returns the passed <code><phrase role="identifier">std</phrase><phrase
  8631. role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>.
  8632. </para>
  8633. </listitem>
  8634. </varlistentry>
  8635. <varlistentry>
  8636. <term>Throws:</term>
  8637. <listitem>
  8638. <para>
  8639. <code><phrase role="identifier">future_error</phrase></code> with
  8640. error condition <code><phrase role="identifier">future_errc</phrase><phrase
  8641. role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
  8642. </para>
  8643. </listitem>
  8644. </varlistentry>
  8645. <varlistentry>
  8646. <term>Note:</term>
  8647. <listitem>
  8648. <para>
  8649. <code><phrase role="identifier">get_exception_ptr</phrase><phrase
  8650. role="special">()</phrase></code> does <emphasis>not</emphasis> invalidate
  8651. the <code>future</code>. After calling <code><phrase role="identifier">get_exception_ptr</phrase><phrase
  8652. role="special">()</phrase></code>, you may still call <link linkend="future_get"><code>future::get()</code></link>.
  8653. </para>
  8654. </listitem>
  8655. </varlistentry>
  8656. </variablelist>
  8657. <para>
  8658. <bridgehead renderas="sect4" id="future_wait_bridgehead">
  8659. <phrase id="future_wait"/>
  8660. <link linkend="future_wait">Member function <code>wait</code>()</link>
  8661. </bridgehead>
  8662. </para>
  8663. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
  8664. </programlisting>
  8665. <variablelist>
  8666. <title></title>
  8667. <varlistentry>
  8668. <term>Effects:</term>
  8669. <listitem>
  8670. <para>
  8671. Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is
  8672. called.
  8673. </para>
  8674. </listitem>
  8675. </varlistentry>
  8676. <varlistentry>
  8677. <term>Throws:</term>
  8678. <listitem>
  8679. <para>
  8680. <code><phrase role="identifier">future_error</phrase></code> with
  8681. error condition <code><phrase role="identifier">future_errc</phrase><phrase
  8682. role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
  8683. </para>
  8684. </listitem>
  8685. </varlistentry>
  8686. </variablelist>
  8687. <para>
  8688. <bridgehead renderas="sect4" id="future_wait_for_bridgehead">
  8689. <phrase id="future_wait_for"/>
  8690. <link linkend="future_wait_for">Templated member
  8691. function <code>wait_for</code>()</link>
  8692. </bridgehead>
  8693. </para>
  8694. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  8695. <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
  8696. </programlisting>
  8697. <variablelist>
  8698. <title></title>
  8699. <varlistentry>
  8700. <term>Effects:</term>
  8701. <listitem>
  8702. <para>
  8703. Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is
  8704. called, or <code><phrase role="identifier">timeout_duration</phrase></code>
  8705. has passed.
  8706. </para>
  8707. </listitem>
  8708. </varlistentry>
  8709. <varlistentry>
  8710. <term>Result:</term>
  8711. <listitem>
  8712. <para>
  8713. A <code><phrase role="identifier">future_status</phrase></code> is
  8714. returned indicating the reason for returning.
  8715. </para>
  8716. </listitem>
  8717. </varlistentry>
  8718. <varlistentry>
  8719. <term>Throws:</term>
  8720. <listitem>
  8721. <para>
  8722. <code><phrase role="identifier">future_error</phrase></code> with
  8723. error condition <code><phrase role="identifier">future_errc</phrase><phrase
  8724. role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
  8725. or timeout-related exceptions.
  8726. </para>
  8727. </listitem>
  8728. </varlistentry>
  8729. </variablelist>
  8730. <para>
  8731. <bridgehead renderas="sect4" id="future_wait_until_bridgehead">
  8732. <phrase id="future_wait_until"/>
  8733. <link linkend="future_wait_until">Templated
  8734. member function <code>wait_until</code>()</link>
  8735. </bridgehead>
  8736. </para>
  8737. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  8738. <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
  8739. </programlisting>
  8740. <variablelist>
  8741. <title></title>
  8742. <varlistentry>
  8743. <term>Effects:</term>
  8744. <listitem>
  8745. <para>
  8746. Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is
  8747. called, or <code><phrase role="identifier">timeout_time</phrase></code>
  8748. has passed.
  8749. </para>
  8750. </listitem>
  8751. </varlistentry>
  8752. <varlistentry>
  8753. <term>Result:</term>
  8754. <listitem>
  8755. <para>
  8756. A <code><phrase role="identifier">future_status</phrase></code> is
  8757. returned indicating the reason for returning.
  8758. </para>
  8759. </listitem>
  8760. </varlistentry>
  8761. <varlistentry>
  8762. <term>Throws:</term>
  8763. <listitem>
  8764. <para>
  8765. <code><phrase role="identifier">future_error</phrase></code> with
  8766. error condition <code><phrase role="identifier">future_errc</phrase><phrase
  8767. role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
  8768. or timeout-related exceptions.
  8769. </para>
  8770. </listitem>
  8771. </varlistentry>
  8772. </variablelist>
  8773. <para>
  8774. <bridgehead renderas="sect4" id="class_shared_future_bridgehead">
  8775. <phrase id="class_shared_future"/>
  8776. <link linkend="class_shared_future">Template
  8777. <code>shared_future&lt;&gt;</code></link>
  8778. </bridgehead>
  8779. </para>
  8780. <para>
  8781. A <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> contains a <link linkend="shared_state">shared
  8782. state</link> which might be shared with other <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> instances.
  8783. </para>
  8784. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">future</phrase><phrase role="special">/</phrase><phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  8785. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  8786. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  8787. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase>
  8788. <phrase role="keyword">class</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">{</phrase>
  8789. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  8790. <phrase role="identifier">shared_future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8791. <phrase role="special">~</phrase><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase>
  8792. <phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
  8793. <phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8794. <phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8795. <phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8796. <phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8797. <phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8798. <phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8799. <phrase role="identifier">R</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of generic shared_future template</phrase>
  8800. <phrase role="identifier">R</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of shared_future&lt; R &amp; &gt; template specialization</phrase>
  8801. <phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of shared_future&lt; void &gt; template specialization</phrase>
  8802. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase>
  8803. <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
  8804. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  8805. <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase>
  8806. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
  8807. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  8808. <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase>
  8809. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
  8810. <phrase role="special">};</phrase>
  8811. <phrase role="special">}}</phrase>
  8812. </programlisting>
  8813. <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h7">
  8814. <phrase id="fiber.synchronization.futures.future.default_constructor0"/><link
  8815. linkend="fiber.synchronization.futures.future.default_constructor0">Default
  8816. constructor</link>
  8817. </bridgehead>
  8818. <programlisting><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase>
  8819. </programlisting>
  8820. <variablelist>
  8821. <title></title>
  8822. <varlistentry>
  8823. <term>Effects:</term>
  8824. <listitem>
  8825. <para>
  8826. Creates a shared_future with no <link linkend="shared_state">shared
  8827. state</link>. After construction <code><phrase role="keyword">false</phrase>
  8828. <phrase role="special">==</phrase> <phrase role="identifier">valid</phrase><phrase
  8829. role="special">()</phrase></code>.
  8830. </para>
  8831. </listitem>
  8832. </varlistentry>
  8833. <varlistentry>
  8834. <term>Throws:</term>
  8835. <listitem>
  8836. <para>
  8837. Nothing.
  8838. </para>
  8839. </listitem>
  8840. </varlistentry>
  8841. </variablelist>
  8842. <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h8">
  8843. <phrase id="fiber.synchronization.futures.future.move_constructor0"/><link
  8844. linkend="fiber.synchronization.futures.future.move_constructor0">Move constructor</link>
  8845. </bridgehead>
  8846. <programlisting><phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8847. <phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8848. </programlisting>
  8849. <variablelist>
  8850. <title></title>
  8851. <varlistentry>
  8852. <term>Effects:</term>
  8853. <listitem>
  8854. <para>
  8855. Constructs a shared_future with the <link linkend="shared_state">shared
  8856. state</link> of other. After construction <code><phrase role="keyword">false</phrase>
  8857. <phrase role="special">==</phrase> <phrase role="identifier">other</phrase><phrase
  8858. role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
  8859. role="special">()</phrase></code>.
  8860. </para>
  8861. </listitem>
  8862. </varlistentry>
  8863. <varlistentry>
  8864. <term>Throws:</term>
  8865. <listitem>
  8866. <para>
  8867. Nothing.
  8868. </para>
  8869. </listitem>
  8870. </varlistentry>
  8871. </variablelist>
  8872. <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h9">
  8873. <phrase id="fiber.synchronization.futures.future.copy_constructor"/><link
  8874. linkend="fiber.synchronization.futures.future.copy_constructor">Copy constructor</link>
  8875. </bridgehead>
  8876. <programlisting><phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8877. </programlisting>
  8878. <variablelist>
  8879. <title></title>
  8880. <varlistentry>
  8881. <term>Effects:</term>
  8882. <listitem>
  8883. <para>
  8884. Constructs a shared_future with the <link linkend="shared_state">shared
  8885. state</link> of other. After construction <code><phrase role="identifier">other</phrase><phrase
  8886. role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
  8887. role="special">()</phrase></code> is unchanged.
  8888. </para>
  8889. </listitem>
  8890. </varlistentry>
  8891. <varlistentry>
  8892. <term>Throws:</term>
  8893. <listitem>
  8894. <para>
  8895. Nothing.
  8896. </para>
  8897. </listitem>
  8898. </varlistentry>
  8899. </variablelist>
  8900. <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h10">
  8901. <phrase id="fiber.synchronization.futures.future.destructor0"/><link linkend="fiber.synchronization.futures.future.destructor0">Destructor</link>
  8902. </bridgehead>
  8903. <programlisting><phrase role="special">~</phrase><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase>
  8904. </programlisting>
  8905. <variablelist>
  8906. <title></title>
  8907. <varlistentry>
  8908. <term>Effects:</term>
  8909. <listitem>
  8910. <para>
  8911. Destroys the shared_future; ownership is abandoned if not shared.
  8912. </para>
  8913. </listitem>
  8914. </varlistentry>
  8915. <varlistentry>
  8916. <term>Note:</term>
  8917. <listitem>
  8918. <para>
  8919. <code>~shared_future()</code> does <emphasis>not</emphasis> block the calling fiber.
  8920. </para>
  8921. </listitem>
  8922. </varlistentry>
  8923. </variablelist>
  8924. <para>
  8925. <bridgehead renderas="sect4" id="shared_future_operator_assign_bridgehead">
  8926. <phrase id="shared_future_operator_assign"/>
  8927. <link linkend="shared_future_operator_assign">Member
  8928. function <code>operator=</code>()</link>
  8929. </bridgehead>
  8930. </para>
  8931. <programlisting><phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8932. <phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8933. <phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8934. </programlisting>
  8935. <variablelist>
  8936. <title></title>
  8937. <varlistentry>
  8938. <term>Effects:</term>
  8939. <listitem>
  8940. <para>
  8941. Moves or copies the <link linkend="shared_state">shared state</link>
  8942. of other to <code><phrase role="keyword">this</phrase></code>. After
  8943. the assignment, the state of <code><phrase role="identifier">other</phrase><phrase
  8944. role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
  8945. role="special">()</phrase></code> depends on which overload was invoked:
  8946. unchanged for the overload accepting <code><phrase role="identifier">shared_future</phrase>
  8947. <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></code>,
  8948. otherwise <code><phrase role="keyword">false</phrase></code>.
  8949. </para>
  8950. </listitem>
  8951. </varlistentry>
  8952. <varlistentry>
  8953. <term>Throws:</term>
  8954. <listitem>
  8955. <para>
  8956. Nothing.
  8957. </para>
  8958. </listitem>
  8959. </varlistentry>
  8960. </variablelist>
  8961. <para>
  8962. <bridgehead renderas="sect4" id="shared_future_valid_bridgehead">
  8963. <phrase id="shared_future_valid"/>
  8964. <link linkend="shared_future_valid">Member
  8965. function <code>valid</code>()</link>
  8966. </bridgehead>
  8967. </para>
  8968. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  8969. </programlisting>
  8970. <variablelist>
  8971. <title></title>
  8972. <varlistentry>
  8973. <term>Effects:</term>
  8974. <listitem>
  8975. <para>
  8976. Returns <code><phrase role="keyword">true</phrase></code> if shared_future
  8977. contains a <link linkend="shared_state">shared state</link>.
  8978. </para>
  8979. </listitem>
  8980. </varlistentry>
  8981. <varlistentry>
  8982. <term>Throws:</term>
  8983. <listitem>
  8984. <para>
  8985. Nothing.
  8986. </para>
  8987. </listitem>
  8988. </varlistentry>
  8989. </variablelist>
  8990. <para>
  8991. <bridgehead renderas="sect4" id="shared_future_get_bridgehead">
  8992. <phrase id="shared_future_get"/>
  8993. <link linkend="shared_future_get">Member function
  8994. <code>get</code>()</link>
  8995. </bridgehead>
  8996. </para>
  8997. <programlisting><phrase role="identifier">R</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of generic shared_future template</phrase>
  8998. <phrase role="identifier">R</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of shared_future&lt; R &amp; &gt; template specialization</phrase>
  8999. <phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of shared_future&lt; void &gt; template specialization</phrase>
  9000. </programlisting>
  9001. <variablelist>
  9002. <title></title>
  9003. <varlistentry>
  9004. <term>Precondition:</term>
  9005. <listitem>
  9006. <para>
  9007. <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
  9008. <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
  9009. </para>
  9010. </listitem>
  9011. </varlistentry>
  9012. <varlistentry>
  9013. <term>Returns:</term>
  9014. <listitem>
  9015. <para>
  9016. Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is
  9017. called. If <link linkend="promise_set_value"><code>promise::set_value()</code></link> is called, returns
  9018. the value. If <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is called,
  9019. throws the indicated exception.
  9020. </para>
  9021. </listitem>
  9022. </varlistentry>
  9023. <varlistentry>
  9024. <term>Postcondition:</term>
  9025. <listitem>
  9026. <para>
  9027. <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
  9028. <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
  9029. </para>
  9030. </listitem>
  9031. </varlistentry>
  9032. <varlistentry>
  9033. <term>Throws:</term>
  9034. <listitem>
  9035. <para>
  9036. <code><phrase role="identifier">future_error</phrase></code> with
  9037. error condition <code><phrase role="identifier">future_errc</phrase><phrase
  9038. role="special">::</phrase><phrase role="identifier">no_state</phrase></code>,
  9039. <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
  9040. role="identifier">broken_promise</phrase></code>. Any exception passed
  9041. to <code><phrase role="identifier">promise</phrase><phrase role="special">::</phrase><phrase
  9042. role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>.
  9043. </para>
  9044. </listitem>
  9045. </varlistentry>
  9046. </variablelist>
  9047. <para>
  9048. <bridgehead renderas="sect4" id="shared_future_get_exception_ptr_bridgehead">
  9049. <phrase id="shared_future_get_exception_ptr"/>
  9050. <link linkend="shared_future_get_exception_ptr">Member
  9051. function <code>get_exception_ptr</code>()</link>
  9052. </bridgehead>
  9053. </para>
  9054. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase>
  9055. </programlisting>
  9056. <variablelist>
  9057. <title></title>
  9058. <varlistentry>
  9059. <term>Precondition:</term>
  9060. <listitem>
  9061. <para>
  9062. <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
  9063. <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
  9064. </para>
  9065. </listitem>
  9066. </varlistentry>
  9067. <varlistentry>
  9068. <term>Returns:</term>
  9069. <listitem>
  9070. <para>
  9071. Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is
  9072. called. If <code><phrase role="identifier">set_value</phrase><phrase
  9073. role="special">()</phrase></code> is called, returns a default-constructed
  9074. <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  9075. role="identifier">exception_ptr</phrase></code>. If <code><phrase
  9076. role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>
  9077. is called, returns the passed <code><phrase role="identifier">std</phrase><phrase
  9078. role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>.
  9079. </para>
  9080. </listitem>
  9081. </varlistentry>
  9082. <varlistentry>
  9083. <term>Throws:</term>
  9084. <listitem>
  9085. <para>
  9086. <code><phrase role="identifier">future_error</phrase></code> with
  9087. error condition <code><phrase role="identifier">future_errc</phrase><phrase
  9088. role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
  9089. </para>
  9090. </listitem>
  9091. </varlistentry>
  9092. <varlistentry>
  9093. <term>Note:</term>
  9094. <listitem>
  9095. <para>
  9096. <code><phrase role="identifier">get_exception_ptr</phrase><phrase
  9097. role="special">()</phrase></code> does <emphasis>not</emphasis> invalidate
  9098. the <code>shared_future</code>. After calling <code><phrase role="identifier">get_exception_ptr</phrase><phrase
  9099. role="special">()</phrase></code>, you may still call <link linkend="shared_future_get"><code>shared_future::get()</code></link>.
  9100. </para>
  9101. </listitem>
  9102. </varlistentry>
  9103. </variablelist>
  9104. <para>
  9105. <bridgehead renderas="sect4" id="shared_future_wait_bridgehead">
  9106. <phrase id="shared_future_wait"/>
  9107. <link linkend="shared_future_wait">Member
  9108. function <code>wait</code>()</link>
  9109. </bridgehead>
  9110. </para>
  9111. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
  9112. </programlisting>
  9113. <variablelist>
  9114. <title></title>
  9115. <varlistentry>
  9116. <term>Effects:</term>
  9117. <listitem>
  9118. <para>
  9119. Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is
  9120. called.
  9121. </para>
  9122. </listitem>
  9123. </varlistentry>
  9124. <varlistentry>
  9125. <term>Throws:</term>
  9126. <listitem>
  9127. <para>
  9128. <code><phrase role="identifier">future_error</phrase></code> with
  9129. error condition <code><phrase role="identifier">future_errc</phrase><phrase
  9130. role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
  9131. </para>
  9132. </listitem>
  9133. </varlistentry>
  9134. </variablelist>
  9135. <para>
  9136. <bridgehead renderas="sect4" id="shared_future_wait_for_bridgehead">
  9137. <phrase id="shared_future_wait_for"/>
  9138. <link linkend="shared_future_wait_for">Templated
  9139. member function <code>wait_for</code>()</link>
  9140. </bridgehead>
  9141. </para>
  9142. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
  9143. <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
  9144. </programlisting>
  9145. <variablelist>
  9146. <title></title>
  9147. <varlistentry>
  9148. <term>Effects:</term>
  9149. <listitem>
  9150. <para>
  9151. Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is
  9152. called, or <code><phrase role="identifier">timeout_duration</phrase></code>
  9153. has passed.
  9154. </para>
  9155. </listitem>
  9156. </varlistentry>
  9157. <varlistentry>
  9158. <term>Result:</term>
  9159. <listitem>
  9160. <para>
  9161. A <code><phrase role="identifier">future_status</phrase></code> is
  9162. returned indicating the reason for returning.
  9163. </para>
  9164. </listitem>
  9165. </varlistentry>
  9166. <varlistentry>
  9167. <term>Throws:</term>
  9168. <listitem>
  9169. <para>
  9170. <code><phrase role="identifier">future_error</phrase></code> with
  9171. error condition <code><phrase role="identifier">future_errc</phrase><phrase
  9172. role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
  9173. or timeout-related exceptions.
  9174. </para>
  9175. </listitem>
  9176. </varlistentry>
  9177. </variablelist>
  9178. <para>
  9179. <bridgehead renderas="sect4" id="shared_future_wait_until_bridgehead">
  9180. <phrase id="shared_future_wait_until"/>
  9181. <link linkend="shared_future_wait_until">Templated
  9182. member function <code>wait_until</code>()</link>
  9183. </bridgehead>
  9184. </para>
  9185. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
  9186. <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
  9187. </programlisting>
  9188. <variablelist>
  9189. <title></title>
  9190. <varlistentry>
  9191. <term>Effects:</term>
  9192. <listitem>
  9193. <para>
  9194. Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is
  9195. called, or <code><phrase role="identifier">timeout_time</phrase></code>
  9196. has passed.
  9197. </para>
  9198. </listitem>
  9199. </varlistentry>
  9200. <varlistentry>
  9201. <term>Result:</term>
  9202. <listitem>
  9203. <para>
  9204. A <code><phrase role="identifier">future_status</phrase></code> is
  9205. returned indicating the reason for returning.
  9206. </para>
  9207. </listitem>
  9208. </varlistentry>
  9209. <varlistentry>
  9210. <term>Throws:</term>
  9211. <listitem>
  9212. <para>
  9213. <code><phrase role="identifier">future_error</phrase></code> with
  9214. error condition <code><phrase role="identifier">future_errc</phrase><phrase
  9215. role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
  9216. or timeout-related exceptions.
  9217. </para>
  9218. </listitem>
  9219. </varlistentry>
  9220. </variablelist>
  9221. <para>
  9222. <bridgehead renderas="sect4" id="fibers_async_bridgehead">
  9223. <phrase id="fibers_async"/>
  9224. <link linkend="fibers_async">Non-member function <code>fibers::async()</code></link>
  9225. </bridgehead>
  9226. </para>
  9227. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">future</phrase><phrase role="special">/</phrase><phrase role="identifier">async</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  9228. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  9229. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  9230. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Function</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  9231. <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
  9232. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
  9233. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase>
  9234. <phrase role="special">&gt;</phrase>
  9235. <phrase role="special">&gt;</phrase>
  9236. <phrase role="identifier">async</phrase><phrase role="special">(</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
  9237. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Function</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  9238. <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
  9239. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
  9240. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase>
  9241. <phrase role="special">&gt;</phrase>
  9242. <phrase role="special">&gt;</phrase>
  9243. <phrase role="identifier">async</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
  9244. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Function</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  9245. <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
  9246. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
  9247. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase>
  9248. <phrase role="special">&gt;</phrase>
  9249. <phrase role="special">&gt;</phrase>
  9250. <phrase role="identifier">async</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase>
  9251. <phrase role="identifier">Function</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
  9252. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Function</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  9253. <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
  9254. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
  9255. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase>
  9256. <phrase role="special">&gt;</phrase>
  9257. <phrase role="special">&gt;</phrase>
  9258. <phrase role="identifier">async</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase>
  9259. <phrase role="identifier">Allocator</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">,</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
  9260. <phrase role="special">}}</phrase>
  9261. </programlisting>
  9262. <variablelist>
  9263. <title></title>
  9264. <varlistentry>
  9265. <term>Effects:</term>
  9266. <listitem>
  9267. <para>
  9268. Executes <code><phrase role="identifier">fn</phrase></code> in a
  9269. <link linkend="class_fiber"><code>fiber</code></link> and returns an associated <link linkend="class_future"><code>future&lt;&gt;</code></link>.
  9270. </para>
  9271. </listitem>
  9272. </varlistentry>
  9273. <varlistentry>
  9274. <term>Result:</term>
  9275. <listitem>
  9276. <para>
  9277. <programlisting><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
  9278. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
  9279. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase>
  9280. <phrase role="special">&gt;</phrase>
  9281. <phrase role="special">&gt;</phrase></programlisting>
  9282. representing the <link linkend="shared_state">shared state</link>
  9283. associated with the asynchronous execution of <code><phrase role="identifier">fn</phrase></code>.
  9284. </para>
  9285. </listitem>
  9286. </varlistentry>
  9287. <varlistentry>
  9288. <term>Throws:</term>
  9289. <listitem>
  9290. <para>
  9291. <code><phrase role="identifier">fiber_error</phrase></code> or <code><phrase
  9292. role="identifier">future_error</phrase></code> if an error occurs.
  9293. </para>
  9294. </listitem>
  9295. </varlistentry>
  9296. <varlistentry>
  9297. <term>Notes:</term>
  9298. <listitem>
  9299. <para>
  9300. The overloads accepting <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
  9301. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  9302. role="identifier">allocator_arg_t</phrase></code></ulink> use the
  9303. passed <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link>
  9304. when constructing the launched <code><phrase role="identifier">fiber</phrase></code>.
  9305. The overloads accepting <link linkend="class_launch"><code>launch</code></link> use the passed <code><phrase
  9306. role="identifier">launch</phrase></code> when constructing the launched
  9307. <code><phrase role="identifier">fiber</phrase></code>. The default
  9308. <code><phrase role="identifier">launch</phrase></code> is <code><phrase
  9309. role="identifier">post</phrase></code>, as for the <code><phrase
  9310. role="identifier">fiber</phrase></code> constructor.
  9311. </para>
  9312. </listitem>
  9313. </varlistentry>
  9314. </variablelist>
  9315. <note>
  9316. <para>
  9317. Deferred futures are not supported.
  9318. </para>
  9319. </note>
  9320. </section>
  9321. <section id="fiber.synchronization.futures.promise">
  9322. <title><anchor id="class_promise"/><link linkend="fiber.synchronization.futures.promise">Template
  9323. <code><phrase role="identifier">promise</phrase><phrase role="special">&lt;&gt;</phrase></code></link></title>
  9324. <para>
  9325. A <link linkend="class_promise"><code>promise&lt;&gt;</code></link> provides a mechanism to store a value (or
  9326. exception) that can later be retrieved from the corresponding <link linkend="class_future"><code>future&lt;&gt;</code></link> object.
  9327. <code><phrase role="identifier">promise</phrase><phrase role="special">&lt;&gt;</phrase></code>
  9328. and <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
  9329. communicate via their underlying <link linkend="shared_state">shared state</link>.
  9330. </para>
  9331. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">future</phrase><phrase role="special">/</phrase><phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  9332. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  9333. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  9334. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase>
  9335. <phrase role="keyword">class</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">{</phrase>
  9336. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  9337. <phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
  9338. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="special">&gt;</phrase>
  9339. <phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">);</phrase>
  9340. <phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9341. <phrase role="identifier">promise</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9342. <phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  9343. <phrase role="identifier">promise</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">promise</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  9344. <phrase role="special">~</phrase><phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
  9345. <phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9346. <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
  9347. <phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;);</phrase> <phrase role="comment">// member only of generic promise template</phrase>
  9348. <phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&amp;&amp;);</phrase> <phrase role="comment">// member only of generic promise template</phrase>
  9349. <phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&amp;);</phrase> <phrase role="comment">// member only of promise&lt; R &amp; &gt; template</phrase>
  9350. <phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of promise&lt; void &gt; template</phrase>
  9351. <phrase role="keyword">void</phrase> <phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">p</phrase><phrase role="special">);</phrase>
  9352. <phrase role="special">};</phrase>
  9353. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase>
  9354. <phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;,</phrase> <phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9355. <phrase role="special">}</phrase>
  9356. </programlisting>
  9357. <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h0">
  9358. <phrase id="fiber.synchronization.futures.promise.default_constructor"/><link
  9359. linkend="fiber.synchronization.futures.promise.default_constructor">Default
  9360. constructor</link>
  9361. </bridgehead>
  9362. <programlisting><phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
  9363. </programlisting>
  9364. <variablelist>
  9365. <title></title>
  9366. <varlistentry>
  9367. <term>Effects:</term>
  9368. <listitem>
  9369. <para>
  9370. Creates a promise with an empty <link linkend="shared_state">shared
  9371. state</link>.
  9372. </para>
  9373. </listitem>
  9374. </varlistentry>
  9375. <varlistentry>
  9376. <term>Throws:</term>
  9377. <listitem>
  9378. <para>
  9379. Exceptions caused by memory allocation.
  9380. </para>
  9381. </listitem>
  9382. </varlistentry>
  9383. </variablelist>
  9384. <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h1">
  9385. <phrase id="fiber.synchronization.futures.promise.constructor"/><link linkend="fiber.synchronization.futures.promise.constructor">Constructor</link>
  9386. </bridgehead>
  9387. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="special">&gt;</phrase>
  9388. <phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase>
  9389. </programlisting>
  9390. <variablelist>
  9391. <title></title>
  9392. <varlistentry>
  9393. <term>Effects:</term>
  9394. <listitem>
  9395. <para>
  9396. Creates a promise with an empty <link linkend="shared_state">shared
  9397. state</link> by using <code><phrase role="identifier">alloc</phrase></code>.
  9398. </para>
  9399. </listitem>
  9400. </varlistentry>
  9401. <varlistentry>
  9402. <term>Throws:</term>
  9403. <listitem>
  9404. <para>
  9405. Exceptions caused by memory allocation.
  9406. </para>
  9407. </listitem>
  9408. </varlistentry>
  9409. <varlistentry>
  9410. <term>See also:</term>
  9411. <listitem>
  9412. <para>
  9413. <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
  9414. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  9415. role="identifier">allocator_arg_t</phrase></code></ulink>
  9416. </para>
  9417. </listitem>
  9418. </varlistentry>
  9419. </variablelist>
  9420. <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h2">
  9421. <phrase id="fiber.synchronization.futures.promise.move_constructor"/><link
  9422. linkend="fiber.synchronization.futures.promise.move_constructor">Move constructor</link>
  9423. </bridgehead>
  9424. <programlisting><phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9425. </programlisting>
  9426. <variablelist>
  9427. <title></title>
  9428. <varlistentry>
  9429. <term>Effects:</term>
  9430. <listitem>
  9431. <para>
  9432. Creates a promise by moving the <link linkend="shared_state">shared
  9433. state</link> from <code><phrase role="identifier">other</phrase></code>.
  9434. </para>
  9435. </listitem>
  9436. </varlistentry>
  9437. <varlistentry>
  9438. <term>Postcondition:</term>
  9439. <listitem>
  9440. <para>
  9441. <code><phrase role="identifier">other</phrase></code> contains no
  9442. valid shared state.
  9443. </para>
  9444. </listitem>
  9445. </varlistentry>
  9446. <varlistentry>
  9447. <term>Throws:</term>
  9448. <listitem>
  9449. <para>
  9450. Nothing.
  9451. </para>
  9452. </listitem>
  9453. </varlistentry>
  9454. </variablelist>
  9455. <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h3">
  9456. <phrase id="fiber.synchronization.futures.promise.destructor"/><link linkend="fiber.synchronization.futures.promise.destructor">Destructor</link>
  9457. </bridgehead>
  9458. <programlisting><phrase role="special">~</phrase><phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
  9459. </programlisting>
  9460. <variablelist>
  9461. <title></title>
  9462. <varlistentry>
  9463. <term>Effects:</term>
  9464. <listitem>
  9465. <para>
  9466. Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  9467. and abandons the <link linkend="shared_state">shared state</link>
  9468. if shared state is ready; otherwise stores <code><phrase role="identifier">future_error</phrase></code>
  9469. with error condition <code><phrase role="identifier">future_errc</phrase><phrase
  9470. role="special">::</phrase><phrase role="identifier">broken_promise</phrase></code>
  9471. as if by <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>: the shared
  9472. state is set ready.
  9473. </para>
  9474. </listitem>
  9475. </varlistentry>
  9476. </variablelist>
  9477. <para>
  9478. <bridgehead renderas="sect4" id="promise_operator_assign_bridgehead">
  9479. <phrase id="promise_operator_assign"/>
  9480. <link linkend="promise_operator_assign">Member
  9481. function <code>operator=</code>()</link>
  9482. </bridgehead>
  9483. </para>
  9484. <programlisting><phrase role="identifier">promise</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9485. </programlisting>
  9486. <variablelist>
  9487. <title></title>
  9488. <varlistentry>
  9489. <term>Effects:</term>
  9490. <listitem>
  9491. <para>
  9492. Transfers the ownership of <link linkend="shared_state">shared state</link>
  9493. to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
  9494. </para>
  9495. </listitem>
  9496. </varlistentry>
  9497. <varlistentry>
  9498. <term>Postcondition:</term>
  9499. <listitem>
  9500. <para>
  9501. <code><phrase role="identifier">other</phrase></code> contains no
  9502. valid shared state.
  9503. </para>
  9504. </listitem>
  9505. </varlistentry>
  9506. <varlistentry>
  9507. <term>Throws:</term>
  9508. <listitem>
  9509. <para>
  9510. Nothing.
  9511. </para>
  9512. </listitem>
  9513. </varlistentry>
  9514. </variablelist>
  9515. <para>
  9516. <bridgehead renderas="sect4" id="promise_swap_bridgehead">
  9517. <phrase id="promise_swap"/>
  9518. <link linkend="promise_swap">Member function <code>swap</code>()</link>
  9519. </bridgehead>
  9520. </para>
  9521. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9522. </programlisting>
  9523. <variablelist>
  9524. <title></title>
  9525. <varlistentry>
  9526. <term>Effects:</term>
  9527. <listitem>
  9528. <para>
  9529. Swaps the <link linkend="shared_state">shared state</link> between
  9530. other and <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
  9531. </para>
  9532. </listitem>
  9533. </varlistentry>
  9534. <varlistentry>
  9535. <term>Throws:</term>
  9536. <listitem>
  9537. <para>
  9538. Nothing.
  9539. </para>
  9540. </listitem>
  9541. </varlistentry>
  9542. </variablelist>
  9543. <para>
  9544. <bridgehead renderas="sect4" id="promise_get_future_bridgehead">
  9545. <phrase id="promise_get_future"/>
  9546. <link linkend="promise_get_future">Member
  9547. function <code>get_future</code>()</link>
  9548. </bridgehead>
  9549. </para>
  9550. <programlisting><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
  9551. </programlisting>
  9552. <variablelist>
  9553. <title></title>
  9554. <varlistentry>
  9555. <term>Returns:</term>
  9556. <listitem>
  9557. <para>
  9558. A <link linkend="class_future"><code>future&lt;&gt;</code></link> with the same <link linkend="shared_state">shared
  9559. state</link>.
  9560. </para>
  9561. </listitem>
  9562. </varlistentry>
  9563. <varlistentry>
  9564. <term>Throws:</term>
  9565. <listitem>
  9566. <para>
  9567. <code><phrase role="identifier">future_error</phrase></code> with
  9568. <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
  9569. role="identifier">future_already_retrieved</phrase></code> or <code><phrase
  9570. role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
  9571. role="identifier">no_state</phrase></code>.
  9572. </para>
  9573. </listitem>
  9574. </varlistentry>
  9575. </variablelist>
  9576. <para>
  9577. <bridgehead renderas="sect4" id="promise_set_value_bridgehead">
  9578. <phrase id="promise_set_value"/>
  9579. <link linkend="promise_set_value">Member function
  9580. <code>set_value</code>()</link>
  9581. </bridgehead>
  9582. </para>
  9583. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase> <phrase role="comment">// member only of generic promise template</phrase>
  9584. <phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase> <phrase role="comment">// member only of generic promise template</phrase>
  9585. <phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase> <phrase role="comment">// member only of promise&lt; R &amp; &gt; template</phrase>
  9586. <phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of promise&lt; void &gt; template</phrase>
  9587. </programlisting>
  9588. <variablelist>
  9589. <title></title>
  9590. <varlistentry>
  9591. <term>Effects:</term>
  9592. <listitem>
  9593. <para>
  9594. Store the result in the <link linkend="shared_state">shared state</link>
  9595. and marks the state as ready.
  9596. </para>
  9597. </listitem>
  9598. </varlistentry>
  9599. <varlistentry>
  9600. <term>Throws:</term>
  9601. <listitem>
  9602. <para>
  9603. <code><phrase role="identifier">future_error</phrase></code> with
  9604. <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
  9605. role="identifier">future_already_satisfied</phrase></code> or <code><phrase
  9606. role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
  9607. role="identifier">no_state</phrase></code>.
  9608. </para>
  9609. </listitem>
  9610. </varlistentry>
  9611. </variablelist>
  9612. <para>
  9613. <bridgehead renderas="sect4" id="promise_set_exception_bridgehead">
  9614. <phrase id="promise_set_exception"/>
  9615. <link linkend="promise_set_exception">Member
  9616. function <code>set_exception</code>()</link>
  9617. </bridgehead>
  9618. </para>
  9619. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase><phrase role="special">);</phrase>
  9620. </programlisting>
  9621. <variablelist>
  9622. <title></title>
  9623. <varlistentry>
  9624. <term>Effects:</term>
  9625. <listitem>
  9626. <para>
  9627. Store an exception pointer in the <link linkend="shared_state">shared
  9628. state</link> and marks the state as ready.
  9629. </para>
  9630. </listitem>
  9631. </varlistentry>
  9632. <varlistentry>
  9633. <term>Throws:</term>
  9634. <listitem>
  9635. <para>
  9636. <code><phrase role="identifier">future_error</phrase></code> with
  9637. <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
  9638. role="identifier">future_already_satisfied</phrase></code> or <code><phrase
  9639. role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
  9640. role="identifier">no_state</phrase></code>.
  9641. </para>
  9642. </listitem>
  9643. </varlistentry>
  9644. </variablelist>
  9645. <para>
  9646. <bridgehead renderas="sect4" id="swap_for_promise_bridgehead">
  9647. <phrase id="swap_for_promise"/>
  9648. <link linkend="swap_for_promise">Non-member function
  9649. <code>swap()</code></link>
  9650. </bridgehead>
  9651. </para>
  9652. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase>
  9653. <phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9654. </programlisting>
  9655. <variablelist>
  9656. <title></title>
  9657. <varlistentry>
  9658. <term>Effects:</term>
  9659. <listitem>
  9660. <para>
  9661. Same as <code><phrase role="identifier">l</phrase><phrase role="special">.</phrase><phrase
  9662. role="identifier">swap</phrase><phrase role="special">(</phrase>
  9663. <phrase role="identifier">r</phrase><phrase role="special">)</phrase></code>.
  9664. </para>
  9665. </listitem>
  9666. </varlistentry>
  9667. </variablelist>
  9668. </section>
  9669. <section id="fiber.synchronization.futures.packaged_task">
  9670. <title><anchor id="class_packaged_task"/><link linkend="fiber.synchronization.futures.packaged_task">Template
  9671. <code><phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;&gt;</phrase></code></link></title>
  9672. <para>
  9673. A <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> wraps a callable target that
  9674. returns a value so that the return value can be computed asynchronously.
  9675. </para>
  9676. <para>
  9677. Conventional usage of <code><phrase role="identifier">packaged_task</phrase><phrase
  9678. role="special">&lt;&gt;</phrase></code> is like this:
  9679. </para>
  9680. <orderedlist>
  9681. <listitem>
  9682. <simpara>
  9683. Instantiate <code><phrase role="identifier">packaged_task</phrase><phrase
  9684. role="special">&lt;&gt;</phrase></code> with template arguments matching
  9685. the signature of the callable. Pass the callable to the <link linkend="packaged_task_packaged_task">constructor</link>.
  9686. </simpara>
  9687. </listitem>
  9688. <listitem>
  9689. <simpara>
  9690. Call <link linkend="packaged_task_get_future"><code>packaged_task::get_future()</code></link> and capture
  9691. the returned <link linkend="class_future"><code>future&lt;&gt;</code></link> instance.
  9692. </simpara>
  9693. </listitem>
  9694. <listitem>
  9695. <simpara>
  9696. Launch a <link linkend="class_fiber"><code>fiber</code></link> to run the new <code><phrase role="identifier">packaged_task</phrase><phrase
  9697. role="special">&lt;&gt;</phrase></code>, passing any arguments required
  9698. by the original callable.
  9699. </simpara>
  9700. </listitem>
  9701. <listitem>
  9702. <simpara>
  9703. Call <link linkend="fiber_detach"><code>fiber::detach()</code></link> on the newly-launched <code><phrase
  9704. role="identifier">fiber</phrase></code>.
  9705. </simpara>
  9706. </listitem>
  9707. <listitem>
  9708. <simpara>
  9709. At some later point, retrieve the result from the <code><phrase role="identifier">future</phrase><phrase
  9710. role="special">&lt;&gt;</phrase></code>.
  9711. </simpara>
  9712. </listitem>
  9713. </orderedlist>
  9714. <para>
  9715. This is, in fact, pretty much what <link linkend="fibers_async"><code>fibers::async()</code></link>
  9716. encapsulates.
  9717. </para>
  9718. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">future</phrase><phrase role="special">/</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  9719. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  9720. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  9721. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">R</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
  9722. <phrase role="keyword">class</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase><phrase role="special">(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
  9723. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  9724. <phrase role="identifier">packaged_task</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9725. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;</phrase>
  9726. <phrase role="keyword">explicit</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;);</phrase>
  9727. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="special">&gt;</phrase>
  9728. <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;);</phrase>
  9729. <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9730. <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9731. <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  9732. <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  9733. <phrase role="special">~</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">();</phrase>
  9734. <phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9735. <phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9736. <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
  9737. <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">...);</phrase>
  9738. <phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">();</phrase>
  9739. <phrase role="special">};</phrase>
  9740. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">&gt;</phrase>
  9741. <phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;,</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9742. <phrase role="special">}}</phrase>
  9743. </programlisting>
  9744. <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h0">
  9745. <phrase id="fiber.synchronization.futures.packaged_task.default_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_"/><link
  9746. linkend="fiber.synchronization.futures.packaged_task.default_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_">Default
  9747. constructor <code><phrase role="identifier">packaged_task</phrase><phrase
  9748. role="special">()</phrase></code></link>
  9749. </bridgehead>
  9750. <programlisting><phrase role="identifier">packaged_task</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9751. </programlisting>
  9752. <variablelist>
  9753. <title></title>
  9754. <varlistentry>
  9755. <term>Effects:</term>
  9756. <listitem>
  9757. <para>
  9758. Constructs an object of class <code><phrase role="identifier">packaged_task</phrase></code>
  9759. with no <link linkend="shared_state">shared state</link>.
  9760. </para>
  9761. </listitem>
  9762. </varlistentry>
  9763. <varlistentry>
  9764. <term>Throws:</term>
  9765. <listitem>
  9766. <para>
  9767. Nothing.
  9768. </para>
  9769. </listitem>
  9770. </varlistentry>
  9771. </variablelist>
  9772. <anchor id="packaged_task_packaged_task"/>
  9773. <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h1">
  9774. <phrase id="fiber.synchronization.futures.packaged_task.templated_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_"/><link
  9775. linkend="fiber.synchronization.futures.packaged_task.templated_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_">Templated
  9776. constructor <code><phrase role="identifier">packaged_task</phrase><phrase
  9777. role="special">()</phrase></code></link>
  9778. </bridgehead>
  9779. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;</phrase>
  9780. <phrase role="keyword">explicit</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">fn</phrase><phrase role="special">);</phrase>
  9781. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="special">&gt;</phrase>
  9782. <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">fn</phrase><phrase role="special">);</phrase>
  9783. </programlisting>
  9784. <variablelist>
  9785. <title></title>
  9786. <varlistentry>
  9787. <term>Effects:</term>
  9788. <listitem>
  9789. <para>
  9790. Constructs an object of class <code><phrase role="identifier">packaged_task</phrase></code>
  9791. with a <link linkend="shared_state">shared state</link> and copies
  9792. or moves the callable target <code><phrase role="identifier">fn</phrase></code>
  9793. to internal storage.
  9794. </para>
  9795. </listitem>
  9796. </varlistentry>
  9797. <varlistentry>
  9798. <term>Throws:</term>
  9799. <listitem>
  9800. <para>
  9801. Exceptions caused by memory allocation.
  9802. </para>
  9803. </listitem>
  9804. </varlistentry>
  9805. <varlistentry>
  9806. <term>Note:</term>
  9807. <listitem>
  9808. <para>
  9809. The signature of <code><phrase role="identifier">Fn</phrase></code>
  9810. should have a return type convertible to <code><phrase role="identifier">R</phrase></code>.
  9811. </para>
  9812. </listitem>
  9813. </varlistentry>
  9814. <varlistentry>
  9815. <term>See also:</term>
  9816. <listitem>
  9817. <para>
  9818. <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
  9819. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  9820. role="identifier">allocator_arg_t</phrase></code></ulink>
  9821. </para>
  9822. </listitem>
  9823. </varlistentry>
  9824. </variablelist>
  9825. <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h2">
  9826. <phrase id="fiber.synchronization.futures.packaged_task.move_constructor"/><link
  9827. linkend="fiber.synchronization.futures.packaged_task.move_constructor">Move
  9828. constructor</link>
  9829. </bridgehead>
  9830. <programlisting><phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9831. </programlisting>
  9832. <variablelist>
  9833. <title></title>
  9834. <varlistentry>
  9835. <term>Effects:</term>
  9836. <listitem>
  9837. <para>
  9838. Creates a packaged_task by moving the <link linkend="shared_state">shared
  9839. state</link> from <code><phrase role="identifier">other</phrase></code>.
  9840. </para>
  9841. </listitem>
  9842. </varlistentry>
  9843. <varlistentry>
  9844. <term>Postcondition:</term>
  9845. <listitem>
  9846. <para>
  9847. <code><phrase role="identifier">other</phrase></code> contains no
  9848. valid shared state.
  9849. </para>
  9850. </listitem>
  9851. </varlistentry>
  9852. <varlistentry>
  9853. <term>Throws:</term>
  9854. <listitem>
  9855. <para>
  9856. Nothing.
  9857. </para>
  9858. </listitem>
  9859. </varlistentry>
  9860. </variablelist>
  9861. <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h3">
  9862. <phrase id="fiber.synchronization.futures.packaged_task.destructor"/><link
  9863. linkend="fiber.synchronization.futures.packaged_task.destructor">Destructor</link>
  9864. </bridgehead>
  9865. <programlisting><phrase role="special">~</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">();</phrase>
  9866. </programlisting>
  9867. <variablelist>
  9868. <title></title>
  9869. <varlistentry>
  9870. <term>Effects:</term>
  9871. <listitem>
  9872. <para>
  9873. Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
  9874. and abandons the <link linkend="shared_state">shared state</link>
  9875. if shared state is ready; otherwise stores <code><phrase role="identifier">future_error</phrase></code>
  9876. with error condition <code><phrase role="identifier">future_errc</phrase><phrase
  9877. role="special">::</phrase><phrase role="identifier">broken_promise</phrase></code>
  9878. as if by <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>: the shared
  9879. state is set ready.
  9880. </para>
  9881. </listitem>
  9882. </varlistentry>
  9883. </variablelist>
  9884. <para>
  9885. <bridgehead renderas="sect4" id="packaged_task_operator_assign_bridgehead">
  9886. <phrase id="packaged_task_operator_assign"/>
  9887. <link linkend="packaged_task_operator_assign">Member
  9888. function <code>operator=</code>()</link>
  9889. </bridgehead>
  9890. </para>
  9891. <programlisting><phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9892. </programlisting>
  9893. <variablelist>
  9894. <title></title>
  9895. <varlistentry>
  9896. <term>Effects:</term>
  9897. <listitem>
  9898. <para>
  9899. Transfers the ownership of <link linkend="shared_state">shared state</link>
  9900. to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
  9901. </para>
  9902. </listitem>
  9903. </varlistentry>
  9904. <varlistentry>
  9905. <term>Postcondition:</term>
  9906. <listitem>
  9907. <para>
  9908. <code><phrase role="identifier">other</phrase></code> contains no
  9909. valid shared state.
  9910. </para>
  9911. </listitem>
  9912. </varlistentry>
  9913. <varlistentry>
  9914. <term>Throws:</term>
  9915. <listitem>
  9916. <para>
  9917. Nothing.
  9918. </para>
  9919. </listitem>
  9920. </varlistentry>
  9921. </variablelist>
  9922. <para>
  9923. <bridgehead renderas="sect4" id="packaged_task_swap_bridgehead">
  9924. <phrase id="packaged_task_swap"/>
  9925. <link linkend="packaged_task_swap">Member
  9926. function <code>swap</code>()</link>
  9927. </bridgehead>
  9928. </para>
  9929. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9930. </programlisting>
  9931. <variablelist>
  9932. <title></title>
  9933. <varlistentry>
  9934. <term>Effects:</term>
  9935. <listitem>
  9936. <para>
  9937. Swaps the <link linkend="shared_state">shared state</link> between
  9938. other and <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
  9939. </para>
  9940. </listitem>
  9941. </varlistentry>
  9942. <varlistentry>
  9943. <term>Throws:</term>
  9944. <listitem>
  9945. <para>
  9946. Nothing.
  9947. </para>
  9948. </listitem>
  9949. </varlistentry>
  9950. </variablelist>
  9951. <para>
  9952. <bridgehead renderas="sect4" id="packaged_task_valid_bridgehead">
  9953. <phrase id="packaged_task_valid"/>
  9954. <link linkend="packaged_task_valid">Member
  9955. function <code>valid</code>()</link>
  9956. </bridgehead>
  9957. </para>
  9958. <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  9959. </programlisting>
  9960. <variablelist>
  9961. <title></title>
  9962. <varlistentry>
  9963. <term>Effects:</term>
  9964. <listitem>
  9965. <para>
  9966. Returns <code><phrase role="keyword">true</phrase></code> if <code><phrase
  9967. role="special">*</phrase><phrase role="keyword">this</phrase></code>
  9968. contains a <link linkend="shared_state">shared state</link>.
  9969. </para>
  9970. </listitem>
  9971. </varlistentry>
  9972. <varlistentry>
  9973. <term>Throws:</term>
  9974. <listitem>
  9975. <para>
  9976. Nothing.
  9977. </para>
  9978. </listitem>
  9979. </varlistentry>
  9980. </variablelist>
  9981. <para>
  9982. <bridgehead renderas="sect4" id="packaged_task_get_future_bridgehead">
  9983. <phrase id="packaged_task_get_future"/>
  9984. <link linkend="packaged_task_get_future">Member
  9985. function <code>get_future</code>()</link>
  9986. </bridgehead>
  9987. </para>
  9988. <programlisting><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
  9989. </programlisting>
  9990. <variablelist>
  9991. <title></title>
  9992. <varlistentry>
  9993. <term>Returns:</term>
  9994. <listitem>
  9995. <para>
  9996. A <link linkend="class_future"><code>future&lt;&gt;</code></link> with the same <link linkend="shared_state">shared
  9997. state</link>.
  9998. </para>
  9999. </listitem>
  10000. </varlistentry>
  10001. <varlistentry>
  10002. <term>Throws:</term>
  10003. <listitem>
  10004. <para>
  10005. <code><phrase role="identifier">future_error</phrase></code> with
  10006. <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
  10007. role="identifier">future_already_retrieved</phrase></code> or <code><phrase
  10008. role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
  10009. role="identifier">no_state</phrase></code>.
  10010. </para>
  10011. </listitem>
  10012. </varlistentry>
  10013. </variablelist>
  10014. <para>
  10015. <bridgehead renderas="sect4" id="packaged_task_operator_apply_bridgehead">
  10016. <phrase id="packaged_task_operator_apply"/>
  10017. <link linkend="packaged_task_operator_apply">Member
  10018. function <code>operator()</code>()</link>
  10019. </bridgehead>
  10020. </para>
  10021. <programlisting><phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
  10022. </programlisting>
  10023. <variablelist>
  10024. <title></title>
  10025. <varlistentry>
  10026. <term>Effects:</term>
  10027. <listitem>
  10028. <para>
  10029. Invokes the stored callable target. Any exception thrown by the callable
  10030. target <code><phrase role="identifier">fn</phrase></code> is stored
  10031. in the <link linkend="shared_state">shared state</link> as if by
  10032. <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>. Otherwise, the value
  10033. returned by <code><phrase role="identifier">fn</phrase></code> is
  10034. stored in the shared state as if by <link linkend="promise_set_value"><code>promise::set_value()</code></link>.
  10035. </para>
  10036. </listitem>
  10037. </varlistentry>
  10038. <varlistentry>
  10039. <term>Throws:</term>
  10040. <listitem>
  10041. <para>
  10042. <code><phrase role="identifier">future_error</phrase></code> with
  10043. <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
  10044. role="identifier">no_state</phrase></code>.
  10045. </para>
  10046. </listitem>
  10047. </varlistentry>
  10048. </variablelist>
  10049. <para>
  10050. <bridgehead renderas="sect4" id="packaged_task_reset_bridgehead">
  10051. <phrase id="packaged_task_reset"/>
  10052. <link linkend="packaged_task_reset">Member
  10053. function <code>reset</code>()</link>
  10054. </bridgehead>
  10055. </para>
  10056. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">();</phrase>
  10057. </programlisting>
  10058. <variablelist>
  10059. <title></title>
  10060. <varlistentry>
  10061. <term>Effects:</term>
  10062. <listitem>
  10063. <para>
  10064. Resets the <link linkend="shared_state">shared state</link> and abandons
  10065. the result of previous executions. A new shared state is constructed.
  10066. </para>
  10067. </listitem>
  10068. </varlistentry>
  10069. <varlistentry>
  10070. <term>Throws:</term>
  10071. <listitem>
  10072. <para>
  10073. <code><phrase role="identifier">future_error</phrase></code> with
  10074. <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
  10075. role="identifier">no_state</phrase></code>.
  10076. </para>
  10077. </listitem>
  10078. </varlistentry>
  10079. </variablelist>
  10080. <para>
  10081. <bridgehead renderas="sect4" id="swap_for_packaged_task_bridgehead">
  10082. <phrase id="swap_for_packaged_task"/>
  10083. <link linkend="swap_for_packaged_task">Non-member
  10084. function <code>swap()</code></link>
  10085. </bridgehead>
  10086. </para>
  10087. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">&gt;</phrase>
  10088. <phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  10089. </programlisting>
  10090. <variablelist>
  10091. <title></title>
  10092. <varlistentry>
  10093. <term>Effects:</term>
  10094. <listitem>
  10095. <para>
  10096. Same as <code><phrase role="identifier">l</phrase><phrase role="special">.</phrase><phrase
  10097. role="identifier">swap</phrase><phrase role="special">(</phrase>
  10098. <phrase role="identifier">r</phrase><phrase role="special">)</phrase></code>.
  10099. </para>
  10100. </listitem>
  10101. </varlistentry>
  10102. </variablelist>
  10103. </section>
  10104. </section>
  10105. </section>
  10106. <section id="fiber.fls">
  10107. <title><link linkend="fiber.fls">Fiber local storage</link></title>
  10108. <bridgehead renderas="sect3" id="fiber.fls.h0">
  10109. <phrase id="fiber.fls.synopsis"/><link linkend="fiber.fls.synopsis">Synopsis</link>
  10110. </bridgehead>
  10111. <para>
  10112. Fiber local storage allows a separate instance of a given data item for each
  10113. fiber.
  10114. </para>
  10115. <bridgehead renderas="sect3" id="fiber.fls.h1">
  10116. <phrase id="fiber.fls.cleanup_at_fiber_exit"/><link linkend="fiber.fls.cleanup_at_fiber_exit">Cleanup
  10117. at fiber exit</link>
  10118. </bridgehead>
  10119. <para>
  10120. When a fiber exits, the objects associated with each <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> instance
  10121. are destroyed. By default, the object pointed to by a pointer <code><phrase
  10122. role="identifier">p</phrase></code> is destroyed by invoking <code><phrase
  10123. role="keyword">delete</phrase> <phrase role="identifier">p</phrase></code>,
  10124. but this can be overridden for a specific instance of <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> by
  10125. providing a cleanup routine <code><phrase role="identifier">func</phrase></code>
  10126. to the constructor. In this case, the object is destroyed by invoking <code><phrase
  10127. role="identifier">func</phrase><phrase role="special">(</phrase><phrase role="identifier">p</phrase><phrase
  10128. role="special">)</phrase></code>. The cleanup functions are called in an unspecified
  10129. order.
  10130. </para>
  10131. <para>
  10132. <bridgehead renderas="sect4" id="class_fiber_specific_ptr_bridgehead">
  10133. <phrase id="class_fiber_specific_ptr"/>
  10134. <link linkend="class_fiber_specific_ptr">Class
  10135. <code>fiber_specific_ptr</code></link>
  10136. </bridgehead>
  10137. </para>
  10138. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">fss</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  10139. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  10140. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  10141. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  10142. <phrase role="keyword">class</phrase> <phrase role="identifier">fiber_specific_ptr</phrase> <phrase role="special">{</phrase>
  10143. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  10144. <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">element_type</phrase><phrase role="special">;</phrase>
  10145. <phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
  10146. <phrase role="keyword">explicit</phrase> <phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">(</phrase> <phrase role="keyword">void</phrase><phrase role="special">(*</phrase><phrase role="identifier">fn</phrase><phrase role="special">)(</phrase><phrase role="identifier">T</phrase><phrase role="special">*)</phrase> <phrase role="special">);</phrase>
  10147. <phrase role="special">~</phrase><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
  10148. <phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber_specific_ptr</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  10149. <phrase role="identifier">fiber_specific_ptr</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">fiber_specific_ptr</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  10150. <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  10151. <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="keyword">operator</phrase><phrase role="special">-&gt;()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  10152. <phrase role="identifier">T</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">*()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  10153. <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">release</phrase><phrase role="special">();</phrase>
  10154. <phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="special">*);</phrase>
  10155. <phrase role="special">};</phrase>
  10156. <phrase role="special">}}</phrase>
  10157. </programlisting>
  10158. <bridgehead renderas="sect3" id="fiber.fls.h2">
  10159. <phrase id="fiber.fls.constructor"/><link linkend="fiber.fls.constructor">Constructor</link>
  10160. </bridgehead>
  10161. <programlisting><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
  10162. <phrase role="keyword">explicit</phrase> <phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">(</phrase> <phrase role="keyword">void</phrase><phrase role="special">(*</phrase><phrase role="identifier">fn</phrase><phrase role="special">)(</phrase><phrase role="identifier">T</phrase><phrase role="special">*)</phrase> <phrase role="special">);</phrase>
  10163. </programlisting>
  10164. <variablelist>
  10165. <title></title>
  10166. <varlistentry>
  10167. <term>Requires:</term>
  10168. <listitem>
  10169. <para>
  10170. <code><phrase role="keyword">delete</phrase> <phrase role="keyword">this</phrase><phrase
  10171. role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
  10172. role="special">()</phrase></code> is well-formed; <code><phrase role="identifier">fn</phrase><phrase
  10173. role="special">(</phrase><phrase role="keyword">this</phrase><phrase
  10174. role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
  10175. role="special">())</phrase></code> does not throw
  10176. </para>
  10177. </listitem>
  10178. </varlistentry>
  10179. <varlistentry>
  10180. <term>Effects:</term>
  10181. <listitem>
  10182. <para>
  10183. Construct a <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> object for storing
  10184. a pointer to an object of type <code><phrase role="identifier">T</phrase></code>
  10185. specific to each fiber. When <code><phrase role="identifier">reset</phrase><phrase
  10186. role="special">()</phrase></code> is called, or the fiber exits, <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> calls
  10187. <code><phrase role="identifier">fn</phrase><phrase role="special">(</phrase><phrase
  10188. role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  10189. role="identifier">get</phrase><phrase role="special">())</phrase></code>.
  10190. If the no-arguments constructor is used, the default <code><phrase role="keyword">delete</phrase></code>-based
  10191. cleanup function will be used to destroy the fiber-local objects.
  10192. </para>
  10193. </listitem>
  10194. </varlistentry>
  10195. <varlistentry>
  10196. <term>Throws:</term>
  10197. <listitem>
  10198. <para>
  10199. <code><phrase role="identifier">fiber_error</phrase></code> if an error
  10200. occurs.
  10201. </para>
  10202. </listitem>
  10203. </varlistentry>
  10204. </variablelist>
  10205. <bridgehead renderas="sect3" id="fiber.fls.h3">
  10206. <phrase id="fiber.fls.destructor"/><link linkend="fiber.fls.destructor">Destructor</link>
  10207. </bridgehead>
  10208. <programlisting><phrase role="special">~</phrase><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
  10209. </programlisting>
  10210. <variablelist>
  10211. <title></title>
  10212. <varlistentry>
  10213. <term>Requires:</term>
  10214. <listitem>
  10215. <para>
  10216. All the fiber specific instances associated to this <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link>
  10217. (except
  10218. maybe the one associated to this fiber) must be nullptr.
  10219. </para>
  10220. </listitem>
  10221. </varlistentry>
  10222. <varlistentry>
  10223. <term>Effects:</term>
  10224. <listitem>
  10225. <para>
  10226. Calls <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  10227. role="identifier">reset</phrase><phrase role="special">()</phrase></code>
  10228. to clean up the associated value for the current fiber, and destroys
  10229. <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
  10230. </para>
  10231. </listitem>
  10232. </varlistentry>
  10233. <varlistentry>
  10234. <term>Remarks:</term>
  10235. <listitem>
  10236. <para>
  10237. The requirement is an implementation restriction. If the destructor promised
  10238. to delete instances for all fibers, the implementation would be forced
  10239. to maintain a list of all the fibers having an associated specific ptr,
  10240. which is against the goal of fiber specific data. In general, a <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> should
  10241. outlive the fibers that use it.
  10242. </para>
  10243. </listitem>
  10244. </varlistentry>
  10245. </variablelist>
  10246. <note>
  10247. <para>
  10248. Care needs to be taken to ensure that any fibers still running after an instance
  10249. of <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> has been destroyed do not call
  10250. any member functions on that instance.
  10251. </para>
  10252. </note>
  10253. <para>
  10254. <bridgehead renderas="sect4" id="fiber_specific_ptr_get_bridgehead">
  10255. <phrase id="fiber_specific_ptr_get"/>
  10256. <link linkend="fiber_specific_ptr_get">Member
  10257. function <code>get</code>()</link>
  10258. </bridgehead>
  10259. </para>
  10260. <programlisting><phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  10261. </programlisting>
  10262. <variablelist>
  10263. <title></title>
  10264. <varlistentry>
  10265. <term>Returns:</term>
  10266. <listitem>
  10267. <para>
  10268. The pointer associated with the current fiber.
  10269. </para>
  10270. </listitem>
  10271. </varlistentry>
  10272. <varlistentry>
  10273. <term>Throws:</term>
  10274. <listitem>
  10275. <para>
  10276. Nothing.
  10277. </para>
  10278. </listitem>
  10279. </varlistentry>
  10280. </variablelist>
  10281. <note>
  10282. <para>
  10283. The initial value associated with an instance of <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> is
  10284. <code><phrase role="keyword">nullptr</phrase></code> for each fiber.
  10285. </para>
  10286. </note>
  10287. <para>
  10288. <bridgehead renderas="sect4" id="fiber_specific_ptr_operator_arrow_bridgehead">
  10289. <phrase id="fiber_specific_ptr_operator_arrow"/>
  10290. <link linkend="fiber_specific_ptr_operator_arrow">Member
  10291. function <code>operator-&gt;</code>()</link>
  10292. </bridgehead>
  10293. </para>
  10294. <programlisting><phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="keyword">operator</phrase><phrase role="special">-&gt;()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  10295. </programlisting>
  10296. <variablelist>
  10297. <title></title>
  10298. <varlistentry>
  10299. <term>Requires:</term>
  10300. <listitem>
  10301. <para>
  10302. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  10303. role="identifier">get</phrase><phrase role="special">()</phrase></code>
  10304. is not <code><phrase role="keyword">nullptr</phrase></code>.
  10305. </para>
  10306. </listitem>
  10307. </varlistentry>
  10308. <varlistentry>
  10309. <term>Returns:</term>
  10310. <listitem>
  10311. <para>
  10312. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  10313. role="identifier">get</phrase><phrase role="special">()</phrase></code>
  10314. </para>
  10315. </listitem>
  10316. </varlistentry>
  10317. <varlistentry>
  10318. <term>Throws:</term>
  10319. <listitem>
  10320. <para>
  10321. Nothing.
  10322. </para>
  10323. </listitem>
  10324. </varlistentry>
  10325. </variablelist>
  10326. <para>
  10327. <bridgehead renderas="sect4" id="fiber_specific_ptr_operator_star_bridgehead">
  10328. <phrase id="fiber_specific_ptr_operator_star"/>
  10329. <link linkend="fiber_specific_ptr_operator_star">Member
  10330. function <code>operator*</code>()</link>
  10331. </bridgehead>
  10332. </para>
  10333. <programlisting><phrase role="identifier">T</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">*()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  10334. </programlisting>
  10335. <variablelist>
  10336. <title></title>
  10337. <varlistentry>
  10338. <term>Requires:</term>
  10339. <listitem>
  10340. <para>
  10341. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  10342. role="identifier">get</phrase><phrase role="special">()</phrase></code>
  10343. is not <code><phrase role="keyword">nullptr</phrase></code>.
  10344. </para>
  10345. </listitem>
  10346. </varlistentry>
  10347. <varlistentry>
  10348. <term>Returns:</term>
  10349. <listitem>
  10350. <para>
  10351. <code><phrase role="special">*(</phrase><phrase role="keyword">this</phrase><phrase
  10352. role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
  10353. role="special">())</phrase></code>
  10354. </para>
  10355. </listitem>
  10356. </varlistentry>
  10357. <varlistentry>
  10358. <term>Throws:</term>
  10359. <listitem>
  10360. <para>
  10361. Nothing.
  10362. </para>
  10363. </listitem>
  10364. </varlistentry>
  10365. </variablelist>
  10366. <para>
  10367. <bridgehead renderas="sect4" id="fiber_specific_ptr_release_bridgehead">
  10368. <phrase id="fiber_specific_ptr_release"/>
  10369. <link linkend="fiber_specific_ptr_release">Member
  10370. function <code>release</code>()</link>
  10371. </bridgehead>
  10372. </para>
  10373. <programlisting><phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">release</phrase><phrase role="special">();</phrase>
  10374. </programlisting>
  10375. <variablelist>
  10376. <title></title>
  10377. <varlistentry>
  10378. <term>Effects:</term>
  10379. <listitem>
  10380. <para>
  10381. Return <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  10382. role="identifier">get</phrase><phrase role="special">()</phrase></code>
  10383. and store <code><phrase role="keyword">nullptr</phrase></code> as the
  10384. pointer associated with the current fiber without invoking the cleanup
  10385. function.
  10386. </para>
  10387. </listitem>
  10388. </varlistentry>
  10389. <varlistentry>
  10390. <term>Postcondition:</term>
  10391. <listitem>
  10392. <para>
  10393. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  10394. role="identifier">get</phrase><phrase role="special">()==</phrase><phrase
  10395. role="keyword">nullptr</phrase></code>
  10396. </para>
  10397. </listitem>
  10398. </varlistentry>
  10399. <varlistentry>
  10400. <term>Throws:</term>
  10401. <listitem>
  10402. <para>
  10403. Nothing.
  10404. </para>
  10405. </listitem>
  10406. </varlistentry>
  10407. </variablelist>
  10408. <para>
  10409. <bridgehead renderas="sect4" id="fiber_specific_ptr_reset_bridgehead">
  10410. <phrase id="fiber_specific_ptr_reset"/>
  10411. <link linkend="fiber_specific_ptr_reset">Member
  10412. function <code>reset</code>()</link>
  10413. </bridgehead>
  10414. </para>
  10415. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">new_value</phrase><phrase role="special">);</phrase>
  10416. </programlisting>
  10417. <variablelist>
  10418. <title></title>
  10419. <varlistentry>
  10420. <term>Effects:</term>
  10421. <listitem>
  10422. <para>
  10423. If <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  10424. role="identifier">get</phrase><phrase role="special">()!=</phrase><phrase
  10425. role="identifier">new_value</phrase></code> and <code><phrase role="keyword">this</phrase><phrase
  10426. role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
  10427. role="special">()</phrase></code> is not <code><phrase role="keyword">nullptr</phrase></code>,
  10428. invoke <code><phrase role="keyword">delete</phrase> <phrase role="keyword">this</phrase><phrase
  10429. role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
  10430. role="special">()</phrase></code> or <code><phrase role="identifier">fn</phrase><phrase
  10431. role="special">(</phrase><phrase role="keyword">this</phrase><phrase
  10432. role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
  10433. role="special">())</phrase></code> as appropriate. Store <code><phrase
  10434. role="identifier">new_value</phrase></code> as the pointer associated
  10435. with the current fiber.
  10436. </para>
  10437. </listitem>
  10438. </varlistentry>
  10439. <varlistentry>
  10440. <term>Postcondition:</term>
  10441. <listitem>
  10442. <para>
  10443. <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
  10444. role="identifier">get</phrase><phrase role="special">()==</phrase><phrase
  10445. role="identifier">new_value</phrase></code>
  10446. </para>
  10447. </listitem>
  10448. </varlistentry>
  10449. <varlistentry>
  10450. <term>Throws:</term>
  10451. <listitem>
  10452. <para>
  10453. Exception raised during cleanup of previous value.
  10454. </para>
  10455. </listitem>
  10456. </varlistentry>
  10457. </variablelist>
  10458. </section>
  10459. <section id="fiber.migration">
  10460. <title><anchor id="migration"/><link linkend="fiber.migration">Migrating fibers
  10461. between threads</link></title>
  10462. <bridgehead renderas="sect3" id="fiber.migration.h0">
  10463. <phrase id="fiber.migration.overview"/><link linkend="fiber.migration.overview">Overview</link>
  10464. </bridgehead>
  10465. <para>
  10466. Each fiber owns a stack and manages its execution state, including all registers
  10467. and CPU flags, the instruction pointer and the stack pointer. That means, in
  10468. general, a fiber is not bound to a specific thread.<footnote id="fiber.migration.f0">
  10469. <para>
  10470. The <quote>main</quote> fiber on each thread, that is, the fiber on which
  10471. the thread is launched, cannot migrate to any other thread. Also <emphasis
  10472. role="bold">Boost.Fiber</emphasis> implicitly creates a dispatcher fiber
  10473. for each thread &mdash; this cannot migrate either.
  10474. </para>
  10475. </footnote><superscript>,</superscript><footnote id="fiber.migration.f1">
  10476. <para>
  10477. Of course it would be problematic to migrate a fiber that relies on <link
  10478. linkend="thread_local_storage">thread-local storage</link>.
  10479. </para>
  10480. </footnote>
  10481. </para>
  10482. <para>
  10483. Migrating a fiber from a logical CPU with heavy workload to another logical
  10484. CPU with a lighter workload might speed up the overall execution. Note that
  10485. in the case of NUMA-architectures, it is not always advisable to migrate data
  10486. between threads. Suppose fiber <emphasis>f</emphasis> is running on logical
  10487. CPU <emphasis>cpu0</emphasis> which belongs to NUMA node <emphasis>node0</emphasis>.
  10488. The data of <emphasis>f</emphasis> are allocated on the physical memory located
  10489. at <emphasis>node0</emphasis>. Migrating the fiber from <emphasis>cpu0</emphasis>
  10490. to another logical CPU <emphasis>cpuX</emphasis> which is part of a different
  10491. NUMA node <emphasis>nodeX</emphasis> might reduce the performance of the application
  10492. due to increased latency of memory access.
  10493. </para>
  10494. <para>
  10495. Only fibers that are contained in <link linkend="class_algorithm"><code>algorithm</code></link>&#8217;s ready queue can
  10496. migrate between threads. You cannot migrate a running fiber, nor one that is
  10497. <link linkend="blocking"><emphasis>blocked</emphasis></link>. You cannot migrate
  10498. a fiber if its <link linkend="context_is_context"><code>context::is_context()</code></link> method returns <code><phrase
  10499. role="keyword">true</phrase></code> for <code><phrase role="identifier">pinned_context</phrase></code>.
  10500. </para>
  10501. <para>
  10502. In <emphasis role="bold">Boost.Fiber</emphasis> a fiber is migrated by invoking
  10503. <link linkend="context_detach"><code>context::detach()</code></link> on the thread from which the fiber migrates
  10504. and <link linkend="context_attach"><code>context::attach()</code></link> on the thread to which the fiber migrates.
  10505. </para>
  10506. <para>
  10507. Thus, fiber migration is accomplished by sharing state between instances of
  10508. a user-coded <link linkend="class_algorithm"><code>algorithm</code></link> implementation running on different threads.
  10509. The fiber&#8217;s original thread calls <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>, passing
  10510. the fiber&#8217;s <link linkend="class_context"><code>context</code></link><literal>*</literal>. The <code><phrase role="identifier">awakened</phrase><phrase
  10511. role="special">()</phrase></code> implementation calls <link linkend="context_detach"><code>context::detach()</code></link>.
  10512. </para>
  10513. <para>
  10514. At some later point, when the same or a different thread calls <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>,
  10515. the <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>
  10516. implementation selects a ready fiber and calls <link linkend="context_attach"><code>context::attach()</code></link> on
  10517. it before returning it.
  10518. </para>
  10519. <para>
  10520. As stated above, a <code><phrase role="identifier">context</phrase></code>
  10521. for which <code><phrase role="identifier">is_context</phrase><phrase role="special">(</phrase><phrase
  10522. role="identifier">pinned_context</phrase><phrase role="special">)</phrase>
  10523. <phrase role="special">==</phrase> <phrase role="keyword">true</phrase></code>
  10524. must never be passed to either <link linkend="context_detach"><code>context::detach()</code></link> or <link linkend="context_attach"><code>context::attach()</code></link>.
  10525. It may only be returned from <code><phrase role="identifier">pick_next</phrase><phrase
  10526. role="special">()</phrase></code> called by the <emphasis>same</emphasis> thread
  10527. that passed that context to <code><phrase role="identifier">awakened</phrase><phrase
  10528. role="special">()</phrase></code>.
  10529. </para>
  10530. <bridgehead renderas="sect3" id="fiber.migration.h1">
  10531. <phrase id="fiber.migration.example_of_work_sharing"/><link linkend="fiber.migration.example_of_work_sharing">Example
  10532. of work sharing</link>
  10533. </bridgehead>
  10534. <para>
  10535. In the example <ulink url="../../examples/work_sharing.cpp">work_sharing.cpp</ulink>
  10536. multiple worker fibers are created on the main thread. Each fiber gets a character
  10537. as parameter at construction. This character is printed out ten times. Between
  10538. each iteration the fiber calls <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>. That puts
  10539. the fiber in the ready queue of the fiber-scheduler <emphasis>shared_ready_queue</emphasis>,
  10540. running in the current thread. The next fiber ready to be executed is dequeued
  10541. from the shared ready queue and resumed by <emphasis>shared_ready_queue</emphasis>
  10542. running on <emphasis>any participating thread</emphasis>.
  10543. </para>
  10544. <para>
  10545. All instances of <emphasis>shared_ready_queue</emphasis> share one global concurrent
  10546. queue, used as ready queue. This mechanism shares all worker fibers between
  10547. all instances of <emphasis>shared_ready_queue</emphasis>, thus between all
  10548. participating threads.
  10549. </para>
  10550. <bridgehead renderas="sect3" id="fiber.migration.h2">
  10551. <phrase id="fiber.migration.setup_of_threads_and_fibers"/><link linkend="fiber.migration.setup_of_threads_and_fibers">Setup
  10552. of threads and fibers</link>
  10553. </bridgehead>
  10554. <para>
  10555. In <code><phrase role="identifier">main</phrase><phrase role="special">()</phrase></code>
  10556. the fiber-scheduler is installed and the worker fibers and the threads are
  10557. launched.
  10558. </para>
  10559. <para>
  10560. <programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_work</phrase> <phrase role="special">&gt;();</phrase> <co id="fiber.migration.c0" linkends="fiber.migration.c1" />
  10561. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">char</phrase> <phrase role="identifier">c</phrase> <phrase role="special">:</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">(</phrase><phrase role="string">&quot;abcdefghijklmnopqrstuvwxyz&quot;</phrase><phrase role="special">))</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c2" linkends="fiber.migration.c3" />
  10562. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">([</phrase><phrase role="identifier">c</phrase><phrase role="special">](){</phrase> <phrase role="identifier">whatevah</phrase><phrase role="special">(</phrase> <phrase role="identifier">c</phrase><phrase role="special">);</phrase> <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
  10563. <phrase role="special">++</phrase><phrase role="identifier">fiber_count</phrase><phrase role="special">;</phrase> <co id="fiber.migration.c4" linkends="fiber.migration.c5" />
  10564. <phrase role="special">}</phrase>
  10565. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">thread_barrier</phrase> <phrase role="identifier">b</phrase><phrase role="special">(</phrase> <phrase role="number">4</phrase><phrase role="special">);</phrase>
  10566. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase> <phrase role="identifier">threads</phrase><phrase role="special">[]</phrase> <phrase role="special">=</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c6" linkends="fiber.migration.c7" />
  10567. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">b</phrase><phrase role="special">),</phrase>
  10568. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">b</phrase><phrase role="special">),</phrase>
  10569. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">b</phrase><phrase role="special">)</phrase>
  10570. <phrase role="special">};</phrase>
  10571. <phrase role="identifier">b</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c8" linkends="fiber.migration.c9" />
  10572. <phrase role="special">{</phrase>
  10573. <phrase role="identifier">lock_type</phrase><co id="fiber.migration.c10" linkends="fiber.migration.c11" /> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_count</phrase><phrase role="special">);</phrase>
  10574. <phrase role="identifier">cnd_count</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">fiber_count</phrase><phrase role="special">;</phrase> <phrase role="special">}</phrase> <phrase role="special">);</phrase> <co id="fiber.migration.c12" linkends="fiber.migration.c13" />
  10575. <phrase role="special">}</phrase> <co id="fiber.migration.c14" linkends="fiber.migration.c15" />
  10576. <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">fiber_count</phrase><phrase role="special">);</phrase>
  10577. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">t</phrase> <phrase role="special">:</phrase> <phrase role="identifier">threads</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c16" linkends="fiber.migration.c17" />
  10578. <phrase role="identifier">t</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  10579. <phrase role="special">}</phrase>
  10580. </programlisting>
  10581. </para>
  10582. <calloutlist>
  10583. <callout arearefs="fiber.migration.c0" id="fiber.migration.c1">
  10584. <para>
  10585. Install the scheduling algorithm <code><phrase role="identifier">boost</phrase><phrase
  10586. role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
  10587. role="special">::</phrase><phrase role="identifier">algo</phrase><phrase
  10588. role="special">::</phrase><phrase role="identifier">shared_work</phrase></code>
  10589. in the main thread too, so each new fiber gets launched into the shared
  10590. pool.
  10591. </para>
  10592. </callout>
  10593. <callout arearefs="fiber.migration.c2" id="fiber.migration.c3">
  10594. <para>
  10595. Launch a number of worker fibers; each worker fiber picks up a character
  10596. that is passed as parameter to fiber-function <code><phrase role="identifier">whatevah</phrase></code>.
  10597. Each worker fiber gets detached.
  10598. </para>
  10599. </callout>
  10600. <callout arearefs="fiber.migration.c4" id="fiber.migration.c5">
  10601. <para>
  10602. Increment fiber counter for each new fiber.
  10603. </para>
  10604. </callout>
  10605. <callout arearefs="fiber.migration.c6" id="fiber.migration.c7">
  10606. <para>
  10607. Launch a couple of threads that join the work sharing.
  10608. </para>
  10609. </callout>
  10610. <callout arearefs="fiber.migration.c8" id="fiber.migration.c9">
  10611. <para>
  10612. sync with other threads: allow them to start processing
  10613. </para>
  10614. </callout>
  10615. <callout arearefs="fiber.migration.c10" id="fiber.migration.c11">
  10616. <para>
  10617. <code><phrase role="identifier">lock_type</phrase></code> is typedef'ed
  10618. as <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
  10619. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  10620. role="identifier">unique_lock</phrase></code></ulink>&lt; <ulink url="http://en.cppreference.com/w/cpp/thread/mutex"><code><phrase
  10621. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  10622. role="identifier">mutex</phrase></code></ulink> &gt;
  10623. </para>
  10624. </callout>
  10625. <callout arearefs="fiber.migration.c12" id="fiber.migration.c13">
  10626. <para>
  10627. Suspend main fiber and resume worker fibers in the meanwhile. Main fiber
  10628. gets resumed (e.g returns from <code><phrase role="identifier">condition_variable_any</phrase><phrase
  10629. role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
  10630. role="special">()</phrase></code>) if all worker fibers are complete.
  10631. </para>
  10632. </callout>
  10633. <callout arearefs="fiber.migration.c14" id="fiber.migration.c15">
  10634. <para>
  10635. Releasing lock of mtx_count is required before joining the threads, otherwise
  10636. the other threads would be blocked inside condition_variable::wait() and
  10637. would never return (deadlock).
  10638. </para>
  10639. </callout>
  10640. <callout arearefs="fiber.migration.c16" id="fiber.migration.c17">
  10641. <para>
  10642. wait for threads to terminate
  10643. </para>
  10644. </callout>
  10645. </calloutlist>
  10646. <para>
  10647. The start of the threads is synchronized with a barrier. The main fiber of
  10648. each thread (including main thread) is suspended until all worker fibers are
  10649. complete. When the main fiber returns from <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>,
  10650. the thread terminates: the main thread joins all other threads.
  10651. </para>
  10652. <para>
  10653. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">thread_barrier</phrase> <phrase role="special">*</phrase> <phrase role="identifier">b</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  10654. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase>
  10655. <phrase role="identifier">buffer</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;thread started &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  10656. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">flush</phrase><phrase role="special">;</phrase>
  10657. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_work</phrase> <phrase role="special">&gt;();</phrase> <co id="fiber.migration.c18" linkends="fiber.migration.c19" />
  10658. <phrase role="identifier">b</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c20" linkends="fiber.migration.c21" />
  10659. <phrase role="identifier">lock_type</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_count</phrase><phrase role="special">);</phrase>
  10660. <phrase role="identifier">cnd_count</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">fiber_count</phrase><phrase role="special">;</phrase> <phrase role="special">}</phrase> <phrase role="special">);</phrase> <co id="fiber.migration.c22" linkends="fiber.migration.c23" />
  10661. <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">fiber_count</phrase><phrase role="special">);</phrase>
  10662. <phrase role="special">}</phrase>
  10663. </programlisting>
  10664. </para>
  10665. <calloutlist>
  10666. <callout arearefs="fiber.migration.c18" id="fiber.migration.c19">
  10667. <para>
  10668. Install the scheduling algorithm <code><phrase role="identifier">boost</phrase><phrase
  10669. role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
  10670. role="special">::</phrase><phrase role="identifier">algo</phrase><phrase
  10671. role="special">::</phrase><phrase role="identifier">shared_work</phrase></code>
  10672. in order to join the work sharing.
  10673. </para>
  10674. </callout>
  10675. <callout arearefs="fiber.migration.c20" id="fiber.migration.c21">
  10676. <para>
  10677. sync with other threads: allow them to start processing
  10678. </para>
  10679. </callout>
  10680. <callout arearefs="fiber.migration.c22" id="fiber.migration.c23">
  10681. <para>
  10682. Suspend main fiber and resume worker fibers in the meanwhile. Main fiber
  10683. gets resumed (e.g returns from <code><phrase role="identifier">condition_variable_any</phrase><phrase
  10684. role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
  10685. role="special">()</phrase></code>) if all worker fibers are complete.
  10686. </para>
  10687. </callout>
  10688. </calloutlist>
  10689. <para>
  10690. Each worker fiber executes function <code><phrase role="identifier">whatevah</phrase><phrase
  10691. role="special">()</phrase></code> with character <code><phrase role="identifier">me</phrase></code>
  10692. as parameter. The fiber yields in a loop and prints out a message if it was
  10693. migrated to another thread.
  10694. </para>
  10695. <para>
  10696. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">whatevah</phrase><phrase role="special">(</phrase> <phrase role="keyword">char</phrase> <phrase role="identifier">me</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  10697. <phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
  10698. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">my_thread</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase role="identifier">get_id</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c24" linkends="fiber.migration.c25" />
  10699. <phrase role="special">{</phrase>
  10700. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase>
  10701. <phrase role="identifier">buffer</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;fiber &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">me</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; started on thread &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">my_thread</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="char">'\n'</phrase><phrase role="special">;</phrase>
  10702. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">flush</phrase><phrase role="special">;</phrase>
  10703. <phrase role="special">}</phrase>
  10704. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="number">10</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c26" linkends="fiber.migration.c27" />
  10705. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c28" linkends="fiber.migration.c29" />
  10706. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">new_thread</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase role="identifier">get_id</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c30" linkends="fiber.migration.c31" />
  10707. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">new_thread</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">my_thread</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c32" linkends="fiber.migration.c33" />
  10708. <phrase role="identifier">my_thread</phrase> <phrase role="special">=</phrase> <phrase role="identifier">new_thread</phrase><phrase role="special">;</phrase>
  10709. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase>
  10710. <phrase role="identifier">buffer</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;fiber &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">me</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; switched to thread &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">my_thread</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="char">'\n'</phrase><phrase role="special">;</phrase>
  10711. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">flush</phrase><phrase role="special">;</phrase>
  10712. <phrase role="special">}</phrase>
  10713. <phrase role="special">}</phrase>
  10714. <phrase role="special">}</phrase> <phrase role="keyword">catch</phrase> <phrase role="special">(</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  10715. <phrase role="special">}</phrase>
  10716. <phrase role="identifier">lock_type</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_count</phrase><phrase role="special">);</phrase>
  10717. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="special">--</phrase><phrase role="identifier">fiber_count</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c34" linkends="fiber.migration.c35" />
  10718. <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
  10719. <phrase role="identifier">cnd_count</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c36" linkends="fiber.migration.c37" />
  10720. <phrase role="special">}</phrase>
  10721. <phrase role="special">}</phrase>
  10722. </programlisting>
  10723. </para>
  10724. <calloutlist>
  10725. <callout arearefs="fiber.migration.c24" id="fiber.migration.c25">
  10726. <para>
  10727. get ID of initial thread
  10728. </para>
  10729. </callout>
  10730. <callout arearefs="fiber.migration.c26" id="fiber.migration.c27">
  10731. <para>
  10732. loop ten times
  10733. </para>
  10734. </callout>
  10735. <callout arearefs="fiber.migration.c28" id="fiber.migration.c29">
  10736. <para>
  10737. yield to other fibers
  10738. </para>
  10739. </callout>
  10740. <callout arearefs="fiber.migration.c30" id="fiber.migration.c31">
  10741. <para>
  10742. get ID of current thread
  10743. </para>
  10744. </callout>
  10745. <callout arearefs="fiber.migration.c32" id="fiber.migration.c33">
  10746. <para>
  10747. test if fiber was migrated to another thread
  10748. </para>
  10749. </callout>
  10750. <callout arearefs="fiber.migration.c34" id="fiber.migration.c35">
  10751. <para>
  10752. Decrement fiber counter for each completed fiber.
  10753. </para>
  10754. </callout>
  10755. <callout arearefs="fiber.migration.c36" id="fiber.migration.c37">
  10756. <para>
  10757. Notify all fibers waiting on <code><phrase role="identifier">cnd_count</phrase></code>.
  10758. </para>
  10759. </callout>
  10760. </calloutlist>
  10761. <bridgehead renderas="sect3" id="fiber.migration.h3">
  10762. <phrase id="fiber.migration.scheduling_fibers"/><link linkend="fiber.migration.scheduling_fibers">Scheduling
  10763. fibers</link>
  10764. </bridgehead>
  10765. <para>
  10766. The fiber scheduler <code><phrase role="identifier">shared_ready_queue</phrase></code>
  10767. is like <code><phrase role="identifier">round_robin</phrase></code>, except
  10768. that it shares a common ready queue among all participating threads. A thread
  10769. participates in this pool by executing <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link>
  10770. before
  10771. any other <emphasis role="bold">Boost.Fiber</emphasis> operation.
  10772. </para>
  10773. <para>
  10774. The important point about the ready queue is that it&#8217;s a class static, common
  10775. to all instances of shared_ready_queue. Fibers that are enqueued via <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> (fibers
  10776. that are ready to be resumed) are thus available to all threads. It is required
  10777. to reserve a separate, scheduler-specific queue for the thread&#8217;s main fiber
  10778. and dispatcher fibers: these may <emphasis>not</emphasis> be shared between
  10779. threads! When we&#8217;re passed either of these fibers, push it there instead of
  10780. in the shared queue: it would be Bad News for thread B to retrieve and attempt
  10781. to execute thread A&#8217;s main fiber.
  10782. </para>
  10783. <para>
  10784. [awakened_ws]
  10785. </para>
  10786. <para>
  10787. When <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link> gets called inside one thread,
  10788. a fiber is dequeued from <emphasis>rqueue_</emphasis> and will be resumed in
  10789. that thread.
  10790. </para>
  10791. <para>
  10792. [pick_next_ws]
  10793. </para>
  10794. <para>
  10795. The source code above is found in <ulink url="../../examples/work_sharing.cpp">work_sharing.cpp</ulink>.
  10796. </para>
  10797. </section>
  10798. <section id="fiber.callbacks">
  10799. <title><anchor id="callbacks"/><link linkend="fiber.callbacks">Integrating Fibers
  10800. with Asynchronous Callbacks</link></title>
  10801. <section id="fiber.callbacks.overview">
  10802. <title><link linkend="fiber.callbacks.overview">Overview</link></title>
  10803. <para>
  10804. One of the primary benefits of <emphasis role="bold">Boost.Fiber</emphasis>
  10805. is the ability to use asynchronous operations for efficiency, while at the
  10806. same time structuring the calling code <emphasis>as if</emphasis> the operations
  10807. were synchronous. Asynchronous operations provide completion notification
  10808. in a variety of ways, but most involve a callback function of some kind.
  10809. This section discusses tactics for interfacing <emphasis role="bold">Boost.Fiber</emphasis>
  10810. with an arbitrary async operation.
  10811. </para>
  10812. <para>
  10813. For purposes of illustration, consider the following hypothetical API:
  10814. </para>
  10815. <para>
  10816. <programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">{</phrase>
  10817. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  10818. <phrase role="comment">// constructor acquires some resource that can be read and written</phrase>
  10819. <phrase role="identifier">AsyncAPI</phrase><phrase role="special">();</phrase>
  10820. <phrase role="comment">// callbacks accept an int error code; 0 == success</phrase>
  10821. <phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">errorcode</phrase><phrase role="special">;</phrase>
  10822. <phrase role="comment">// write callback only needs to indicate success or failure</phrase>
  10823. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;</phrase>
  10824. <phrase role="keyword">void</phrase> <phrase role="identifier">init_write</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">callback</phrase><phrase role="special">);</phrase>
  10825. <phrase role="comment">// read callback needs to accept both errorcode and data</phrase>
  10826. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;</phrase>
  10827. <phrase role="keyword">void</phrase> <phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">callback</phrase><phrase role="special">);</phrase>
  10828. <phrase role="comment">// ... other operations ...</phrase>
  10829. <phrase role="special">};</phrase>
  10830. </programlisting>
  10831. </para>
  10832. <para>
  10833. The significant points about each of <code><phrase role="identifier">init_write</phrase><phrase
  10834. role="special">()</phrase></code> and <code><phrase role="identifier">init_read</phrase><phrase
  10835. role="special">()</phrase></code> are:
  10836. </para>
  10837. <itemizedlist>
  10838. <listitem>
  10839. <simpara>
  10840. The <code><phrase role="identifier">AsyncAPI</phrase></code> method only
  10841. initiates the operation. It returns immediately, while the requested
  10842. operation is still pending.
  10843. </simpara>
  10844. </listitem>
  10845. <listitem>
  10846. <simpara>
  10847. The method accepts a callback. When the operation completes, the callback
  10848. is called with relevant parameters (error code, data if applicable).
  10849. </simpara>
  10850. </listitem>
  10851. </itemizedlist>
  10852. <para>
  10853. We would like to wrap these asynchronous methods in functions that appear
  10854. synchronous by blocking the calling fiber until the operation completes.
  10855. This lets us use the wrapper function&#8217;s return value to deliver relevant data.
  10856. </para>
  10857. <tip>
  10858. <para>
  10859. <link linkend="class_promise"><code>promise&lt;&gt;</code></link> and <link linkend="class_future"><code>future&lt;&gt;</code></link> are your friends
  10860. here.
  10861. </para>
  10862. </tip>
  10863. </section>
  10864. <section id="fiber.callbacks.return_errorcode">
  10865. <title><link linkend="fiber.callbacks.return_errorcode">Return Errorcode</link></title>
  10866. <para>
  10867. The <code><phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase
  10868. role="identifier">init_write</phrase><phrase role="special">()</phrase></code>
  10869. callback passes only an <code><phrase role="identifier">errorcode</phrase></code>.
  10870. If we simply want the blocking wrapper to return that <code><phrase role="identifier">errorcode</phrase></code>,
  10871. this is an extremely straightforward use of <link linkend="class_promise"><code>promise&lt;&gt;</code></link> and
  10872. <link linkend="class_future"><code>future&lt;&gt;</code></link>:
  10873. </para>
  10874. <para>
  10875. <programlisting><phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">write_ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  10876. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">promise</phrase><phrase role="special">;</phrase>
  10877. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  10878. <phrase role="comment">// In general, even though we block waiting for future::get() and therefore</phrase>
  10879. <phrase role="comment">// won't destroy 'promise' until promise::set_value() has been called, we</phrase>
  10880. <phrase role="comment">// are advised that with threads it's possible for ~promise() to be</phrase>
  10881. <phrase role="comment">// entered before promise::set_value() has returned. While that shouldn't</phrase>
  10882. <phrase role="comment">// happen with fibers::promise, a robust way to deal with the lifespan</phrase>
  10883. <phrase role="comment">// issue is to bind 'promise' into our lambda. Since promise is move-only,</phrase>
  10884. <phrase role="comment">// use initialization capture.</phrase>
  10885. <phrase role="preprocessor">#if</phrase> <phrase role="special">!</phrase> <phrase role="identifier">defined</phrase><phrase role="special">(</phrase><phrase role="identifier">BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase><phrase role="special">)</phrase>
  10886. <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_write</phrase><phrase role="special">(</phrase>
  10887. <phrase role="identifier">data</phrase><phrase role="special">,</phrase>
  10888. <phrase role="special">[</phrase><phrase role="identifier">promise</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">)](</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase>
  10889. <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase>
  10890. <phrase role="special">});</phrase>
  10891. <phrase role="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase>
  10892. <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_write</phrase><phrase role="special">(</phrase>
  10893. <phrase role="identifier">data</phrase><phrase role="special">,</phrase>
  10894. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">([](</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">promise</phrase><phrase role="special">,</phrase>
  10895. <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  10896. <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase>
  10897. <phrase role="special">},</phrase>
  10898. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">),</phrase>
  10899. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  10900. <phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase>
  10901. <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
  10902. <phrase role="special">}</phrase>
  10903. </programlisting>
  10904. </para>
  10905. <para>
  10906. All we have to do is:
  10907. </para>
  10908. <orderedlist>
  10909. <listitem>
  10910. <simpara>
  10911. Instantiate a <code><phrase role="identifier">promise</phrase><phrase
  10912. role="special">&lt;&gt;</phrase></code> of correct type.
  10913. </simpara>
  10914. </listitem>
  10915. <listitem>
  10916. <simpara>
  10917. Obtain its <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>.
  10918. </simpara>
  10919. </listitem>
  10920. <listitem>
  10921. <simpara>
  10922. Arrange for the callback to call <link linkend="promise_set_value"><code>promise::set_value()</code></link>.
  10923. </simpara>
  10924. </listitem>
  10925. <listitem>
  10926. <simpara>
  10927. Block on <link linkend="future_get"><code>future::get()</code></link>.
  10928. </simpara>
  10929. </listitem>
  10930. </orderedlist>
  10931. <note>
  10932. <para>
  10933. This tactic for resuming a pending fiber works even if the callback is
  10934. called on a different thread than the one on which the initiating fiber
  10935. is running. In fact, <ulink url="../../examples/adapt_callbacks.cpp">the
  10936. example program&#8217;s</ulink> dummy <code><phrase role="identifier">AsyncAPI</phrase></code>
  10937. implementation illustrates that: it simulates async I/O by launching a
  10938. new thread that sleeps briefly and then calls the relevant callback.
  10939. </para>
  10940. </note>
  10941. </section>
  10942. <section id="fiber.callbacks.success_or_exception">
  10943. <title><link linkend="fiber.callbacks.success_or_exception">Success or Exception</link></title>
  10944. <para>
  10945. A wrapper more aligned with modern C++ practice would use an exception, rather
  10946. than an <code><phrase role="identifier">errorcode</phrase></code>, to communicate
  10947. failure to its caller. This is straightforward to code in terms of <code><phrase
  10948. role="identifier">write_ec</phrase><phrase role="special">()</phrase></code>:
  10949. </para>
  10950. <para>
  10951. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">write</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  10952. <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase> <phrase role="special">=</phrase> <phrase role="identifier">write_ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase>
  10953. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  10954. <phrase role="keyword">throw</phrase> <phrase role="identifier">make_exception</phrase><phrase role="special">(</phrase><phrase role="string">&quot;write&quot;</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase>
  10955. <phrase role="special">}</phrase>
  10956. <phrase role="special">}</phrase>
  10957. </programlisting>
  10958. </para>
  10959. <para>
  10960. The point is that since each fiber has its own stack, you need not repeat
  10961. messy boilerplate: normal encapsulation works.
  10962. </para>
  10963. </section>
  10964. <section id="fiber.callbacks.return_errorcode_or_data">
  10965. <title><link linkend="fiber.callbacks.return_errorcode_or_data">Return Errorcode
  10966. or Data</link></title>
  10967. <para>
  10968. Things get a bit more interesting when the async operation&#8217;s callback passes
  10969. multiple data items of interest. One approach would be to use <code><phrase
  10970. role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase
  10971. role="special">&lt;&gt;</phrase></code> to capture both:
  10972. </para>
  10973. <para>
  10974. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">read_ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  10975. <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">result_pair</phrase><phrase role="special">;</phrase>
  10976. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">result_pair</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">promise</phrase><phrase role="special">;</phrase>
  10977. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">result_pair</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  10978. <phrase role="comment">// We promise that both 'promise' and 'future' will survive until our</phrase>
  10979. <phrase role="comment">// lambda has been called.</phrase>
  10980. <phrase role="preprocessor">#if</phrase> <phrase role="special">!</phrase> <phrase role="identifier">defined</phrase><phrase role="special">(</phrase><phrase role="identifier">BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase><phrase role="special">)</phrase>
  10981. <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">([</phrase><phrase role="identifier">promise</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">)](</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase>
  10982. <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">result_pair</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  10983. <phrase role="special">});</phrase>
  10984. <phrase role="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase>
  10985. <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">(</phrase>
  10986. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">([](</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">result_pair</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">promise</phrase><phrase role="special">,</phrase>
  10987. <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase>
  10988. <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">result_pair</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  10989. <phrase role="special">},</phrase>
  10990. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">),</phrase>
  10991. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_1</phrase><phrase role="special">,</phrase>
  10992. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_2</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  10993. <phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase>
  10994. <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
  10995. <phrase role="special">}</phrase>
  10996. </programlisting>
  10997. </para>
  10998. <para>
  10999. Once you bundle the interesting data in <code><phrase role="identifier">std</phrase><phrase
  11000. role="special">::</phrase><phrase role="identifier">pair</phrase><phrase
  11001. role="special">&lt;&gt;</phrase></code>, the code is effectively identical
  11002. to <code><phrase role="identifier">write_ec</phrase><phrase role="special">()</phrase></code>.
  11003. You can call it like this:
  11004. </para>
  11005. <para>
  11006. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tie</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="identifier">read_ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">api</phrase><phrase role="special">);</phrase>
  11007. </programlisting>
  11008. </para>
  11009. </section>
  11010. <section id="fiber.callbacks.data_or_exception">
  11011. <title><anchor id="Data_or_Exception"/><link linkend="fiber.callbacks.data_or_exception">Data
  11012. or Exception</link></title>
  11013. <para>
  11014. But a more natural API for a function that obtains data is to return only
  11015. the data on success, throwing an exception on error.
  11016. </para>
  11017. <para>
  11018. As with <code><phrase role="identifier">write</phrase><phrase role="special">()</phrase></code>
  11019. above, it&#8217;s certainly possible to code a <code><phrase role="identifier">read</phrase><phrase
  11020. role="special">()</phrase></code> wrapper in terms of <code><phrase role="identifier">read_ec</phrase><phrase
  11021. role="special">()</phrase></code>. But since a given application is unlikely
  11022. to need both, let&#8217;s code <code><phrase role="identifier">read</phrase><phrase
  11023. role="special">()</phrase></code> from scratch, leveraging <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>:
  11024. </para>
  11025. <para>
  11026. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11027. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">promise</phrase><phrase role="special">;</phrase>
  11028. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  11029. <phrase role="comment">// Both 'promise' and 'future' will survive until our lambda has been</phrase>
  11030. <phrase role="comment">// called.</phrase>
  11031. <phrase role="preprocessor">#if</phrase> <phrase role="special">!</phrase> <phrase role="identifier">defined</phrase><phrase role="special">(</phrase><phrase role="identifier">BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase><phrase role="special">)</phrase>
  11032. <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">([&amp;</phrase><phrase role="identifier">promise</phrase><phrase role="special">](</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase>
  11033. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11034. <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase>
  11035. <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
  11036. <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase>
  11037. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase>
  11038. <phrase role="identifier">make_exception</phrase><phrase role="special">(</phrase><phrase role="string">&quot;read&quot;</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
  11039. <phrase role="special">}</phrase>
  11040. <phrase role="special">});</phrase>
  11041. <phrase role="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase>
  11042. <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">(</phrase>
  11043. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">([](</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">promise</phrase><phrase role="special">,</phrase>
  11044. <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase>
  11045. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11046. <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase>
  11047. <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
  11048. <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase>
  11049. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase>
  11050. <phrase role="identifier">make_exception</phrase><phrase role="special">(</phrase><phrase role="string">&quot;read&quot;</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
  11051. <phrase role="special">}</phrase>
  11052. <phrase role="special">},</phrase>
  11053. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">),</phrase>
  11054. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_1</phrase><phrase role="special">,</phrase>
  11055. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_2</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  11056. <phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase>
  11057. <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
  11058. <phrase role="special">}</phrase>
  11059. </programlisting>
  11060. </para>
  11061. <para>
  11062. <link linkend="future_get"><code>future::get()</code></link> will do the right thing, either returning <code><phrase
  11063. role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase></code>
  11064. or throwing an exception.
  11065. </para>
  11066. </section>
  11067. <section id="fiber.callbacks.success_error_virtual_methods">
  11068. <title><link linkend="fiber.callbacks.success_error_virtual_methods">Success/Error
  11069. Virtual Methods</link></title>
  11070. <para>
  11071. One classic approach to completion notification is to define an abstract
  11072. base class with <code><phrase role="identifier">success</phrase><phrase role="special">()</phrase></code>
  11073. and <code><phrase role="identifier">error</phrase><phrase role="special">()</phrase></code>
  11074. methods. Code wishing to perform async I/O must derive a subclass, override
  11075. each of these methods and pass the async operation a pointer to a subclass
  11076. instance. The abstract base class might look like this:
  11077. </para>
  11078. <para>
  11079. <programlisting><phrase role="comment">// every async operation receives a subclass instance of this abstract base</phrase>
  11080. <phrase role="comment">// class through which to communicate its result</phrase>
  11081. <phrase role="keyword">struct</phrase> <phrase role="identifier">Response</phrase> <phrase role="special">{</phrase>
  11082. <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Response</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">ptr</phrase><phrase role="special">;</phrase>
  11083. <phrase role="comment">// called if the operation succeeds</phrase>
  11084. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">success</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  11085. <phrase role="comment">// called if the operation fails</phrase>
  11086. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">error</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPIBase</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  11087. <phrase role="special">};</phrase>
  11088. </programlisting>
  11089. </para>
  11090. <para>
  11091. Now the <code><phrase role="identifier">AsyncAPI</phrase></code> operation
  11092. might look more like this:
  11093. </para>
  11094. <para>
  11095. <programlisting><phrase role="comment">// derive Response subclass, instantiate, pass Response::ptr</phrase>
  11096. <phrase role="keyword">void</phrase> <phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> <phrase role="identifier">Response</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr</phrase><phrase role="special">);</phrase>
  11097. </programlisting>
  11098. </para>
  11099. <para>
  11100. We can address this by writing a one-size-fits-all <code><phrase role="identifier">PromiseResponse</phrase></code>:
  11101. </para>
  11102. <para>
  11103. <programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">PromiseResponse</phrase><phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">Response</phrase> <phrase role="special">{</phrase>
  11104. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  11105. <phrase role="comment">// called if the operation succeeds</phrase>
  11106. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">success</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11107. <phrase role="identifier">promise_</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase>
  11108. <phrase role="special">}</phrase>
  11109. <phrase role="comment">// called if the operation fails</phrase>
  11110. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">error</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPIBase</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11111. <phrase role="identifier">promise_</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase>
  11112. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase>
  11113. <phrase role="identifier">make_exception</phrase><phrase role="special">(</phrase><phrase role="string">&quot;read&quot;</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
  11114. <phrase role="special">}</phrase>
  11115. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  11116. <phrase role="keyword">return</phrase> <phrase role="identifier">promise_</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
  11117. <phrase role="special">}</phrase>
  11118. <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
  11119. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">promise_</phrase><phrase role="special">;</phrase>
  11120. <phrase role="special">};</phrase>
  11121. </programlisting>
  11122. </para>
  11123. <para>
  11124. Now we can simply obtain the <code><phrase role="identifier">future</phrase><phrase
  11125. role="special">&lt;&gt;</phrase></code> from that <code><phrase role="identifier">PromiseResponse</phrase></code>
  11126. and wait on its <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>:
  11127. </para>
  11128. <para>
  11129. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11130. <phrase role="comment">// Because init_read() requires a shared_ptr, we must allocate our</phrase>
  11131. <phrase role="comment">// ResponsePromise on the heap, even though we know its lifespan.</phrase>
  11132. <phrase role="keyword">auto</phrase> <phrase role="identifier">promisep</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">PromiseResponse</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
  11133. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">promisep</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  11134. <phrase role="comment">// Both 'promisep' and 'future' will survive until our lambda has been</phrase>
  11135. <phrase role="comment">// called.</phrase>
  11136. <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> <phrase role="identifier">promisep</phrase><phrase role="special">);</phrase>
  11137. <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
  11138. <phrase role="special">}</phrase>
  11139. </programlisting>
  11140. </para>
  11141. <para>
  11142. The source code above is found in <ulink url="../../examples/adapt_callbacks.cpp">adapt_callbacks.cpp</ulink>
  11143. and <ulink url="../../examples/adapt_method_calls.cpp">adapt_method_calls.cpp</ulink>.
  11144. </para>
  11145. </section>
  11146. <section id="fiber.callbacks.then_there_s____boost_asio__">
  11147. <title><anchor id="callbacks_asio"/><link linkend="fiber.callbacks.then_there_s____boost_asio__">Then
  11148. There&#8217;s <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link></title>
  11149. <para>
  11150. Since the simplest form of Boost.Asio asynchronous operation completion token
  11151. is a callback function, we could apply the same tactics for Asio as for our
  11152. hypothetical <code><phrase role="identifier">AsyncAPI</phrase></code> asynchronous
  11153. operations.
  11154. </para>
  11155. <para>
  11156. Fortunately we need not. Boost.Asio incorporates a mechanism<footnote id="fiber.callbacks.then_there_s____boost_asio__.f0">
  11157. <para>
  11158. This mechanism has been proposed as a conventional way to allow the caller
  11159. of an arbitrary async function to specify completion handling: <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4045.pdf">N4045</ulink>.
  11160. </para>
  11161. </footnote> by which the caller can customize the notification behavior of
  11162. any async operation. Therefore we can construct a <emphasis>completion token</emphasis>
  11163. which, when passed to a <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
  11164. async operation, requests blocking for the calling fiber.
  11165. </para>
  11166. <para>
  11167. A typical Asio async function might look something like this:<footnote id="fiber.callbacks.then_there_s____boost_asio__.f1">
  11168. <para>
  11169. per <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4045.pdf">N4045</ulink>
  11170. </para>
  11171. </footnote>
  11172. </para>
  11173. <programlisting><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase> <phrase role="special">...,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">CompletionToken</phrase> <phrase role="special">&gt;</phrase>
  11174. <emphasis>deduced_return_type</emphasis>
  11175. <phrase role="identifier">async_something</phrase><phrase role="special">(</phrase> <phrase role="special">...</phrase> <phrase role="special">,</phrase> <phrase role="identifier">CompletionToken</phrase><phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">token</phrase><phrase role="special">)</phrase>
  11176. <phrase role="special">{</phrase>
  11177. <phrase role="comment">// construct handler_type instance from CompletionToken</phrase>
  11178. <phrase role="identifier">handler_type</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">CompletionToken</phrase><phrase role="special">,</phrase> <phrase role="special">...&gt;::</phrase><phrase role="identifier">type</phrase> <emphasis role="bold"><!--quickbook-escape-prefix--><code><!--quickbook-escape-postfix-->handler(token)<!--quickbook-escape-prefix--></code><!--quickbook-escape-postfix--></emphasis><phrase role="special">;</phrase>
  11179. <phrase role="comment">// construct async_result instance from handler_type</phrase>
  11180. <phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">decltype</phrase><phrase role="special">(</phrase><phrase role="identifier">handler</phrase><phrase role="special">)&gt;</phrase> <emphasis role="bold"><!--quickbook-escape-prefix--><code><!--quickbook-escape-postfix-->result(handler)<!--quickbook-escape-prefix--></code><!--quickbook-escape-postfix--></emphasis><phrase role="special">;</phrase>
  11181. <phrase role="comment">// ... arrange to call handler on completion ...</phrase>
  11182. <phrase role="comment">// ... initiate actual I/O operation ...</phrase>
  11183. <phrase role="keyword">return</phrase> <emphasis role="bold"><!--quickbook-escape-prefix--><code><!--quickbook-escape-postfix-->result.get()<!--quickbook-escape-prefix--></code><!--quickbook-escape-postfix--></emphasis><phrase role="special">;</phrase>
  11184. <phrase role="special">}</phrase>
  11185. </programlisting>
  11186. <para>
  11187. We will engage that mechanism, which is based on specializing Asio&#8217;s <code><phrase
  11188. role="identifier">handler_type</phrase><phrase role="special">&lt;&gt;</phrase></code>
  11189. template for the <code><phrase role="identifier">CompletionToken</phrase></code>
  11190. type and the signature of the specific callback. The remainder of this discussion
  11191. will refer back to <code><phrase role="identifier">async_something</phrase><phrase
  11192. role="special">()</phrase></code> as the Asio async function under consideration.
  11193. </para>
  11194. <para>
  11195. The implementation described below uses lower-level facilities than <code><phrase
  11196. role="identifier">promise</phrase></code> and <code><phrase role="identifier">future</phrase></code>
  11197. because the <code><phrase role="identifier">promise</phrase></code> mechanism
  11198. interacts badly with <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stop.html"><code><phrase
  11199. role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
  11200. role="identifier">stop</phrase><phrase role="special">()</phrase></code></ulink>.
  11201. It produces <code><phrase role="identifier">broken_promise</phrase></code>
  11202. exceptions.
  11203. </para>
  11204. <para>
  11205. <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  11206. role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase
  11207. role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
  11208. role="identifier">yield</phrase></code> is a completion token of this kind.
  11209. <code><phrase role="identifier">yield</phrase></code> is an instance of
  11210. <code><phrase role="identifier">yield_t</phrase></code>:
  11211. </para>
  11212. <para>
  11213. <programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="special">{</phrase>
  11214. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  11215. <phrase role="identifier">yield_t</phrase><phrase role="special">()</phrase> <phrase role="special">=</phrase> <phrase role="keyword">default</phrase><phrase role="special">;</phrase>
  11216. <phrase role="comment">/**
  11217. * @code
  11218. * static yield_t yield;
  11219. * boost::system::error_code myec;
  11220. * func(yield[myec]);
  11221. * @endcode
  11222. * @c yield[myec] returns an instance of @c yield_t whose @c ec_ points
  11223. * to @c myec. The expression @c yield[myec] &quot;binds&quot; @c myec to that
  11224. * (anonymous) @c yield_t instance, instructing @c func() to store any
  11225. * @c error_code it might produce into @c myec rather than throwing @c
  11226. * boost::system::system_error.
  11227. */</phrase>
  11228. <phrase role="identifier">yield_t</phrase> <phrase role="keyword">operator</phrase><phrase role="special">[](</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
  11229. <phrase role="identifier">yield_t</phrase> <phrase role="identifier">tmp</phrase><phrase role="special">;</phrase>
  11230. <phrase role="identifier">tmp</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase> <phrase role="special">=</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">ec</phrase><phrase role="special">;</phrase>
  11231. <phrase role="keyword">return</phrase> <phrase role="identifier">tmp</phrase><phrase role="special">;</phrase>
  11232. <phrase role="special">}</phrase>
  11233. <phrase role="comment">//private:</phrase>
  11234. <phrase role="comment">// ptr to bound error_code instance if any</phrase>
  11235. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">{</phrase> <phrase role="keyword">nullptr</phrase> <phrase role="special">};</phrase>
  11236. <phrase role="special">};</phrase>
  11237. </programlisting>
  11238. </para>
  11239. <para>
  11240. <code><phrase role="identifier">yield_t</phrase></code> is in fact only a
  11241. placeholder, a way to trigger Boost.Asio customization. It can bind a <ulink
  11242. url="http://www.boost.org/doc/libs/release/libs/system/doc/reference.html#Class-error_code"><code><phrase
  11243. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  11244. role="identifier">system</phrase><phrase role="special">::</phrase><phrase
  11245. role="identifier">error_code</phrase></code></ulink> for use by the actual
  11246. handler.
  11247. </para>
  11248. <para>
  11249. <code><phrase role="identifier">yield</phrase></code> is declared as:
  11250. </para>
  11251. <para>
  11252. <programlisting><phrase role="comment">// canonical instance</phrase>
  11253. <phrase role="keyword">thread_local</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="identifier">yield</phrase><phrase role="special">{};</phrase>
  11254. </programlisting>
  11255. </para>
  11256. <para>
  11257. Asio customization is engaged by specializing <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/handler_type.html"><code><phrase
  11258. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  11259. role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
  11260. role="identifier">handler_type</phrase><phrase role="special">&lt;&gt;</phrase></code></ulink>
  11261. for <code><phrase role="identifier">yield_t</phrase></code>:
  11262. </para>
  11263. <para>
  11264. <programlisting><phrase role="comment">// Handler type specialisation for fibers::asio::yield.</phrase>
  11265. <phrase role="comment">// When 'yield' is passed as a completion handler which accepts only</phrase>
  11266. <phrase role="comment">// error_code, use yield_handler&lt;void&gt;. yield_handler will take care of the</phrase>
  11267. <phrase role="comment">// error_code one way or another.</phrase>
  11268. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">ReturnType</phrase> <phrase role="special">&gt;</phrase>
  11269. <phrase role="keyword">struct</phrase> <phrase role="identifier">handler_type</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">ReturnType</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase><phrase role="special">)</phrase> <phrase role="special">&gt;</phrase>
  11270. <phrase role="special">{</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">void</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase>
  11271. </programlisting>
  11272. </para>
  11273. <para>
  11274. (There are actually four different specializations in <ulink url="../../examples/asio/detail/yield.hpp">detail/yield.hpp</ulink>,
  11275. one for each of the four Asio async callback signatures we expect.)
  11276. </para>
  11277. <para>
  11278. The above directs Asio to use <code><phrase role="identifier">yield_handler</phrase></code>
  11279. as the actual handler for an async operation to which <code><phrase role="identifier">yield</phrase></code>
  11280. is passed. There&#8217;s a generic <code><phrase role="identifier">yield_handler</phrase><phrase
  11281. role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></code>
  11282. implementation and a <code><phrase role="identifier">yield_handler</phrase><phrase
  11283. role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
  11284. specialization. Let&#8217;s start with the <code><phrase role="special">&lt;</phrase><phrase
  11285. role="keyword">void</phrase><phrase role="special">&gt;</phrase></code> specialization:
  11286. </para>
  11287. <para>
  11288. <programlisting><phrase role="comment">// yield_handler&lt;void&gt; is like yield_handler&lt;T&gt; without value_. In fact it's</phrase>
  11289. <phrase role="comment">// just like yield_handler_base.</phrase>
  11290. <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
  11291. <phrase role="keyword">class</phrase> <phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">void</phrase> <phrase role="special">&gt;:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">{</phrase>
  11292. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  11293. <phrase role="keyword">explicit</phrase> <phrase role="identifier">yield_handler</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">y</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
  11294. <phrase role="identifier">yield_handler_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">y</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
  11295. <phrase role="special">}</phrase>
  11296. <phrase role="comment">// nullary completion callback</phrase>
  11297. <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()()</phrase> <phrase role="special">{</phrase>
  11298. <phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase role="special">)(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  11299. <phrase role="special">}</phrase>
  11300. <phrase role="comment">// inherit operator()(error_code) overload from base class</phrase>
  11301. <phrase role="keyword">using</phrase> <phrase role="identifier">yield_handler_base</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">();</phrase>
  11302. <phrase role="special">};</phrase>
  11303. </programlisting>
  11304. </para>
  11305. <para>
  11306. <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>,
  11307. having consulted the <code><phrase role="identifier">handler_type</phrase><phrase
  11308. role="special">&lt;&gt;</phrase></code> traits specialization, instantiates
  11309. a <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
  11310. role="keyword">void</phrase><phrase role="special">&gt;</phrase></code> to
  11311. be passed as the actual callback for the async operation. <code><phrase role="identifier">yield_handler</phrase></code>&#8217;s
  11312. constructor accepts the <code><phrase role="identifier">yield_t</phrase></code>
  11313. instance (the <code><phrase role="identifier">yield</phrase></code> object
  11314. passed to the async function) and passes it along to <code><phrase role="identifier">yield_handler_base</phrase></code>:
  11315. </para>
  11316. <para>
  11317. <programlisting><phrase role="comment">// This class encapsulates common elements between yield_handler&lt;T&gt; (capturing</phrase>
  11318. <phrase role="comment">// a value to return from asio async function) and yield_handler&lt;void&gt; (no</phrase>
  11319. <phrase role="comment">// such value). See yield_handler&lt;T&gt; and its &lt;void&gt; specialization below. Both</phrase>
  11320. <phrase role="comment">// yield_handler&lt;T&gt; and yield_handler&lt;void&gt; are passed by value through</phrase>
  11321. <phrase role="comment">// various layers of asio functions. In other words, they're potentially</phrase>
  11322. <phrase role="comment">// copied multiple times. So key data such as the yield_completion instance</phrase>
  11323. <phrase role="comment">// must be stored in our async_result&lt;yield_handler&lt;&gt;&gt; specialization, which</phrase>
  11324. <phrase role="comment">// should be instantiated only once.</phrase>
  11325. <phrase role="keyword">class</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">{</phrase>
  11326. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  11327. <phrase role="identifier">yield_handler_base</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">y</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
  11328. <phrase role="comment">// capture the context* associated with the running fiber</phrase>
  11329. <phrase role="identifier">ctx_</phrase><phrase role="special">{</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">::</phrase><phrase role="identifier">active</phrase><phrase role="special">()</phrase> <phrase role="special">},</phrase>
  11330. <phrase role="comment">// capture the passed yield_t</phrase>
  11331. <phrase role="identifier">yt_</phrase><phrase role="special">(</phrase> <phrase role="identifier">y</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11332. <phrase role="special">}</phrase>
  11333. <phrase role="comment">// completion callback passing only (error_code)</phrase>
  11334. <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11335. <phrase role="identifier">BOOST_ASSERT_MSG</phrase><phrase role="special">(</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">,</phrase>
  11336. <phrase role="string">&quot;Must inject yield_completion* &quot;</phrase>
  11337. <phrase role="string">&quot;before calling yield_handler_base::operator()()&quot;</phrase><phrase role="special">);</phrase>
  11338. <phrase role="identifier">BOOST_ASSERT_MSG</phrase><phrase role="special">(</phrase> <phrase role="identifier">yt_</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase><phrase role="special">,</phrase>
  11339. <phrase role="string">&quot;Must inject boost::system::error_code* &quot;</phrase>
  11340. <phrase role="string">&quot;before calling yield_handler_base::operator()()&quot;</phrase><phrase role="special">);</phrase>
  11341. <phrase role="comment">// If originating fiber is busy testing state_ flag, wait until it</phrase>
  11342. <phrase role="comment">// has observed (completed != state_).</phrase>
  11343. <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">lock_t</phrase> <phrase role="identifier">lk</phrase><phrase role="special">{</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">mtx_</phrase> <phrase role="special">};</phrase>
  11344. <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">state_t</phrase> <phrase role="identifier">state</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">state_</phrase><phrase role="special">;</phrase>
  11345. <phrase role="comment">// Notify a subsequent yield_completion::wait() call that it need not</phrase>
  11346. <phrase role="comment">// suspend.</phrase>
  11347. <phrase role="identifier">ycomp_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">state_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">complete</phrase><phrase role="special">;</phrase>
  11348. <phrase role="comment">// set the error_code bound by yield_t</phrase>
  11349. <phrase role="special">*</phrase> <phrase role="identifier">yt_</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ec</phrase><phrase role="special">;</phrase>
  11350. <phrase role="comment">// unlock the lock that protects state_</phrase>
  11351. <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
  11352. <phrase role="comment">// If ctx_ is still active, e.g. because the async operation</phrase>
  11353. <phrase role="comment">// immediately called its callback (this method!) before the asio</phrase>
  11354. <phrase role="comment">// async function called async_result_base::get(), we must not set it</phrase>
  11355. <phrase role="comment">// ready.</phrase>
  11356. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">waiting</phrase> <phrase role="special">==</phrase> <phrase role="identifier">state</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11357. <phrase role="comment">// wake the fiber</phrase>
  11358. <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">::</phrase><phrase role="identifier">active</phrase><phrase role="special">()-&gt;</phrase><phrase role="identifier">schedule</phrase><phrase role="special">(</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">);</phrase>
  11359. <phrase role="special">}</phrase>
  11360. <phrase role="special">}</phrase>
  11361. <phrase role="comment">//private:</phrase>
  11362. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">;</phrase>
  11363. <phrase role="identifier">yield_t</phrase> <phrase role="identifier">yt_</phrase><phrase role="special">;</phrase>
  11364. <phrase role="comment">// We depend on this pointer to yield_completion, which will be injected</phrase>
  11365. <phrase role="comment">// by async_result.</phrase>
  11366. <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr_t</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">{};</phrase>
  11367. <phrase role="special">};</phrase>
  11368. </programlisting>
  11369. </para>
  11370. <para>
  11371. <code><phrase role="identifier">yield_handler_base</phrase></code> stores
  11372. a copy of the <code><phrase role="identifier">yield_t</phrase></code> instance
  11373. &mdash; which, as shown above, contains only an <code><phrase role="identifier">error_code</phrase><phrase
  11374. role="special">*</phrase></code>. It also captures the <link linkend="class_context"><code>context</code></link>*
  11375. for the currently-running fiber by calling <link linkend="context_active"><code>context::active()</code></link>.
  11376. </para>
  11377. <para>
  11378. You will notice that <code><phrase role="identifier">yield_handler_base</phrase></code>
  11379. has one more data member (<code><phrase role="identifier">ycomp_</phrase></code>)
  11380. that is initialized to <code><phrase role="keyword">nullptr</phrase></code>
  11381. by its constructor &mdash; though its <code><phrase role="keyword">operator</phrase><phrase
  11382. role="special">()()</phrase></code> method relies on <code><phrase role="identifier">ycomp_</phrase></code>
  11383. being non-null. More on this in a moment.
  11384. </para>
  11385. <para>
  11386. Having constructed the <code><phrase role="identifier">yield_handler</phrase><phrase
  11387. role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
  11388. instance, <code><phrase role="identifier">async_something</phrase><phrase
  11389. role="special">()</phrase></code> goes on to construct an <code><phrase role="identifier">async_result</phrase></code>
  11390. specialized for the <code><phrase role="identifier">handler_type</phrase><phrase
  11391. role="special">&lt;&gt;::</phrase><phrase role="identifier">type</phrase></code>:
  11392. in this case, <code><phrase role="identifier">async_result</phrase><phrase
  11393. role="special">&lt;</phrase><phrase role="identifier">yield_handler</phrase><phrase
  11394. role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;&gt;</phrase></code>.
  11395. It passes the <code><phrase role="identifier">yield_handler</phrase><phrase
  11396. role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
  11397. instance to the new <code><phrase role="identifier">async_result</phrase></code>
  11398. instance.
  11399. </para>
  11400. <para>
  11401. <programlisting><phrase role="comment">// Without the need to handle a passed value, our yield_handler&lt;void&gt;</phrase>
  11402. <phrase role="comment">// specialization is just like async_result_base.</phrase>
  11403. <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
  11404. <phrase role="keyword">class</phrase> <phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">void</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">:</phrase>
  11405. <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase> <phrase role="special">{</phrase>
  11406. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  11407. <phrase role="keyword">typedef</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
  11408. <phrase role="keyword">explicit</phrase> <phrase role="identifier">async_result</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">void</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">h</phrase><phrase role="special">):</phrase>
  11409. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">h</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
  11410. <phrase role="special">}</phrase>
  11411. <phrase role="special">};</phrase>
  11412. </programlisting>
  11413. </para>
  11414. <para>
  11415. Naturally that leads us straight to <code><phrase role="identifier">async_result_base</phrase></code>:
  11416. </para>
  11417. <para>
  11418. <programlisting><phrase role="comment">// Factor out commonality between async_result&lt;yield_handler&lt;T&gt;&gt; and</phrase>
  11419. <phrase role="comment">// async_result&lt;yield_handler&lt;void&gt;&gt;</phrase>
  11420. <phrase role="keyword">class</phrase> <phrase role="identifier">async_result_base</phrase> <phrase role="special">{</phrase>
  11421. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  11422. <phrase role="keyword">explicit</phrase> <phrase role="identifier">async_result_base</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">h</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
  11423. <phrase role="identifier">ycomp_</phrase><phrase role="special">{</phrase> <phrase role="keyword">new</phrase> <phrase role="identifier">yield_completion</phrase><phrase role="special">{}</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
  11424. <phrase role="comment">// Inject ptr to our yield_completion instance into this</phrase>
  11425. <phrase role="comment">// yield_handler&lt;&gt;.</phrase>
  11426. <phrase role="identifier">h</phrase><phrase role="special">.</phrase><phrase role="identifier">ycomp_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">ycomp_</phrase><phrase role="special">;</phrase>
  11427. <phrase role="comment">// if yield_t didn't bind an error_code, make yield_handler_base's</phrase>
  11428. <phrase role="comment">// error_code* point to an error_code local to this object so</phrase>
  11429. <phrase role="comment">// yield_handler_base::operator() can unconditionally store through</phrase>
  11430. <phrase role="comment">// its error_code*</phrase>
  11431. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">h</phrase><phrase role="special">.</phrase><phrase role="identifier">yt_</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11432. <phrase role="identifier">h</phrase><phrase role="special">.</phrase><phrase role="identifier">yt_</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase> <phrase role="special">=</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase>
  11433. <phrase role="special">}</phrase>
  11434. <phrase role="special">}</phrase>
  11435. <phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  11436. <phrase role="comment">// Unless yield_handler_base::operator() has already been called,</phrase>
  11437. <phrase role="comment">// suspend the calling fiber until that call.</phrase>
  11438. <phrase role="identifier">ycomp_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
  11439. <phrase role="comment">// The only way our own ec_ member could have a non-default value is</phrase>
  11440. <phrase role="comment">// if our yield_handler did not have a bound error_code AND the</phrase>
  11441. <phrase role="comment">// completion callback passed a non-default error_code.</phrase>
  11442. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11443. <phrase role="identifier">throw_exception</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">system_error</phrase><phrase role="special">{</phrase> <phrase role="identifier">ec_</phrase> <phrase role="special">}</phrase> <phrase role="special">);</phrase>
  11444. <phrase role="special">}</phrase>
  11445. <phrase role="special">}</phrase>
  11446. <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
  11447. <phrase role="comment">// If yield_t does not bind an error_code instance, store into here.</phrase>
  11448. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">{};</phrase>
  11449. <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr_t</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">;</phrase>
  11450. <phrase role="special">};</phrase>
  11451. </programlisting>
  11452. </para>
  11453. <para>
  11454. This is how <code><phrase role="identifier">yield_handler_base</phrase><phrase
  11455. role="special">::</phrase><phrase role="identifier">ycomp_</phrase></code>
  11456. becomes non-null: <code><phrase role="identifier">async_result_base</phrase></code>&#8217;s
  11457. constructor injects a pointer back to its own <code><phrase role="identifier">yield_completion</phrase></code>
  11458. member.
  11459. </para>
  11460. <para>
  11461. Recall that the canonical <code><phrase role="identifier">yield_t</phrase></code>
  11462. instance <code><phrase role="identifier">yield</phrase></code> initializes
  11463. its <code><phrase role="identifier">error_code</phrase><phrase role="special">*</phrase></code>
  11464. member <code><phrase role="identifier">ec_</phrase></code> to <code><phrase
  11465. role="keyword">nullptr</phrase></code>. If this instance is passed to <code><phrase
  11466. role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
  11467. (<code><phrase role="identifier">ec_</phrase></code> is still <code><phrase
  11468. role="keyword">nullptr</phrase></code>), the copy stored in <code><phrase
  11469. role="identifier">yield_handler_base</phrase></code> will likewise have null
  11470. <code><phrase role="identifier">ec_</phrase></code>. <code><phrase role="identifier">async_result_base</phrase></code>&#8217;s
  11471. constructor sets <code><phrase role="identifier">yield_handler_base</phrase></code>&#8217;s
  11472. <code><phrase role="identifier">yield_t</phrase></code>&#8217;s <code><phrase role="identifier">ec_</phrase></code>
  11473. member to point to its own <code><phrase role="identifier">error_code</phrase></code>
  11474. member.
  11475. </para>
  11476. <para>
  11477. The stage is now set. <code><phrase role="identifier">async_something</phrase><phrase
  11478. role="special">()</phrase></code> initiates the actual async operation, arranging
  11479. to call its <code><phrase role="identifier">yield_handler</phrase><phrase
  11480. role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
  11481. instance on completion. Let&#8217;s say, for the sake of argument, that the actual
  11482. async operation&#8217;s callback has signature <code><phrase role="keyword">void</phrase><phrase
  11483. role="special">(</phrase><phrase role="identifier">error_code</phrase><phrase
  11484. role="special">)</phrase></code>.
  11485. </para>
  11486. <para>
  11487. But since it&#8217;s an async operation, control returns at once to <code><phrase
  11488. role="identifier">async_something</phrase><phrase role="special">()</phrase></code>.
  11489. <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
  11490. calls <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
  11491. role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
  11492. role="keyword">void</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
  11493. role="identifier">get</phrase><phrase role="special">()</phrase></code>,
  11494. and will return its return value.
  11495. </para>
  11496. <para>
  11497. <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
  11498. role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
  11499. role="keyword">void</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
  11500. role="identifier">get</phrase><phrase role="special">()</phrase></code> inherits
  11501. <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase
  11502. role="identifier">get</phrase><phrase role="special">()</phrase></code>.
  11503. </para>
  11504. <para>
  11505. <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase
  11506. role="identifier">get</phrase><phrase role="special">()</phrase></code> immediately
  11507. calls <code><phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase
  11508. role="identifier">wait</phrase><phrase role="special">()</phrase></code>.
  11509. </para>
  11510. <para>
  11511. <programlisting><phrase role="comment">// Bundle a completion bool flag with a spinlock to protect it.</phrase>
  11512. <phrase role="keyword">struct</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">{</phrase>
  11513. <phrase role="keyword">enum</phrase> <phrase role="identifier">state_t</phrase> <phrase role="special">{</phrase>
  11514. <phrase role="identifier">init</phrase><phrase role="special">,</phrase>
  11515. <phrase role="identifier">waiting</phrase><phrase role="special">,</phrase>
  11516. <phrase role="identifier">complete</phrase>
  11517. <phrase role="special">};</phrase>
  11518. <phrase role="keyword">typedef</phrase> <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">spinlock</phrase> <phrase role="identifier">mutex_t</phrase><phrase role="special">;</phrase>
  11519. <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">mutex_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lock_t</phrase><phrase role="special">;</phrase>
  11520. <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">intrusive_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">ptr_t</phrase><phrase role="special">;</phrase>
  11521. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">atomic</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">use_count_</phrase><phrase role="special">{</phrase> <phrase role="number">0</phrase> <phrase role="special">};</phrase>
  11522. <phrase role="identifier">mutex_t</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">{};</phrase>
  11523. <phrase role="identifier">state_t</phrase> <phrase role="identifier">state_</phrase><phrase role="special">{</phrase> <phrase role="identifier">init</phrase> <phrase role="special">};</phrase>
  11524. <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  11525. <phrase role="comment">// yield_handler_base::operator()() will set state_ `complete` and</phrase>
  11526. <phrase role="comment">// attempt to wake a suspended fiber. It would be Bad if that call</phrase>
  11527. <phrase role="comment">// happened between our detecting (complete != state_) and suspending.</phrase>
  11528. <phrase role="identifier">lock_t</phrase> <phrase role="identifier">lk</phrase><phrase role="special">{</phrase> <phrase role="identifier">mtx_</phrase> <phrase role="special">};</phrase>
  11529. <phrase role="comment">// If state_ is already set, we're done here: don't suspend.</phrase>
  11530. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">complete</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">state_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11531. <phrase role="identifier">state_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">waiting</phrase><phrase role="special">;</phrase>
  11532. <phrase role="comment">// suspend(unique_lock&lt;spinlock&gt;) unlocks the lock in the act of</phrase>
  11533. <phrase role="comment">// resuming another fiber</phrase>
  11534. <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">::</phrase><phrase role="identifier">active</phrase><phrase role="special">()-&gt;</phrase><phrase role="identifier">suspend</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
  11535. <phrase role="special">}</phrase>
  11536. <phrase role="special">}</phrase>
  11537. <phrase role="keyword">friend</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">intrusive_ptr_add_ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">*</phrase> <phrase role="identifier">yc</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
  11538. <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="keyword">nullptr</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">yc</phrase><phrase role="special">);</phrase>
  11539. <phrase role="identifier">yc</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">use_count_</phrase><phrase role="special">.</phrase><phrase role="identifier">fetch_add</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">memory_order_relaxed</phrase><phrase role="special">);</phrase>
  11540. <phrase role="special">}</phrase>
  11541. <phrase role="keyword">friend</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">intrusive_ptr_release</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">*</phrase> <phrase role="identifier">yc</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
  11542. <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="keyword">nullptr</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">yc</phrase><phrase role="special">);</phrase>
  11543. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">==</phrase> <phrase role="identifier">yc</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">use_count_</phrase><phrase role="special">.</phrase><phrase role="identifier">fetch_sub</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">memory_order_release</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11544. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">atomic_thread_fence</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">memory_order_acquire</phrase><phrase role="special">);</phrase>
  11545. <phrase role="keyword">delete</phrase> <phrase role="identifier">yc</phrase><phrase role="special">;</phrase>
  11546. <phrase role="special">}</phrase>
  11547. <phrase role="special">}</phrase>
  11548. <phrase role="special">};</phrase>
  11549. </programlisting>
  11550. </para>
  11551. <para>
  11552. Supposing that the pending async operation has not yet completed, <code><phrase
  11553. role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase
  11554. role="identifier">completed_</phrase></code> will still be <code><phrase
  11555. role="keyword">false</phrase></code>, and <code><phrase role="identifier">wait</phrase><phrase
  11556. role="special">()</phrase></code> will call <link linkend="context_suspend"><code>context::suspend()</code></link> on
  11557. the currently-running fiber.
  11558. </para>
  11559. <para>
  11560. Other fibers will now have a chance to run.
  11561. </para>
  11562. <para>
  11563. Some time later, the async operation completes. It calls <code><phrase role="identifier">yield_handler</phrase><phrase
  11564. role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase
  11565. role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
  11566. role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase
  11567. role="special">&amp;)</phrase></code> with an <code><phrase role="identifier">error_code</phrase></code>
  11568. indicating either success or failure. We&#8217;ll consider both cases.
  11569. </para>
  11570. <para>
  11571. <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
  11572. role="keyword">void</phrase><phrase role="special">&gt;</phrase></code> explicitly
  11573. inherits <code><phrase role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
  11574. role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase
  11575. role="special">&amp;)</phrase></code> from <code><phrase role="identifier">yield_handler_base</phrase></code>.
  11576. </para>
  11577. <para>
  11578. <code><phrase role="identifier">yield_handler_base</phrase><phrase role="special">::</phrase><phrase
  11579. role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
  11580. role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase
  11581. role="special">&amp;)</phrase></code> first sets <code><phrase role="identifier">yield_completion</phrase><phrase
  11582. role="special">::</phrase><phrase role="identifier">completed_</phrase></code>
  11583. <code><phrase role="keyword">true</phrase></code>. This way, if <code><phrase
  11584. role="identifier">async_something</phrase><phrase role="special">()</phrase></code>&#8217;s
  11585. async operation completes immediately &mdash; if <code><phrase role="identifier">yield_handler_base</phrase><phrase
  11586. role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
  11587. role="special">()</phrase></code> is called even before <code><phrase role="identifier">async_result_base</phrase><phrase
  11588. role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
  11589. &mdash; the calling fiber will <emphasis>not</emphasis> suspend.
  11590. </para>
  11591. <para>
  11592. The actual <code><phrase role="identifier">error_code</phrase></code> produced
  11593. by the async operation is then stored through the stored <code><phrase role="identifier">yield_t</phrase><phrase
  11594. role="special">::</phrase><phrase role="identifier">ec_</phrase></code> pointer.
  11595. If <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>&#8217;s
  11596. caller used (e.g.) <code><phrase role="identifier">yield</phrase><phrase
  11597. role="special">[</phrase><phrase role="identifier">my_ec</phrase><phrase
  11598. role="special">]</phrase></code> to bind a local <code><phrase role="identifier">error_code</phrase></code>
  11599. instance, the actual <code><phrase role="identifier">error_code</phrase></code>
  11600. value is stored into the caller&#8217;s variable. Otherwise, it is stored into
  11601. <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase
  11602. role="identifier">ec_</phrase></code>.
  11603. </para>
  11604. <para>
  11605. If the stored fiber context <code><phrase role="identifier">yield_handler_base</phrase><phrase
  11606. role="special">::</phrase><phrase role="identifier">ctx_</phrase></code>
  11607. is not already running, it is marked as ready to run by passing it to <link linkend="context_schedule"><code>context::schedule()</code></link>.
  11608. Control then returns from <code><phrase role="identifier">yield_handler_base</phrase><phrase
  11609. role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
  11610. role="special">()</phrase></code>: the callback is done.
  11611. </para>
  11612. <para>
  11613. In due course, that fiber is resumed. Control returns from <link linkend="context_suspend"><code>context::suspend()</code></link> to
  11614. <code><phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase
  11615. role="identifier">wait</phrase><phrase role="special">()</phrase></code>,
  11616. which returns to <code><phrase role="identifier">async_result_base</phrase><phrase
  11617. role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>.
  11618. </para>
  11619. <itemizedlist>
  11620. <listitem>
  11621. <simpara>
  11622. If the original caller passed <code><phrase role="identifier">yield</phrase><phrase
  11623. role="special">[</phrase><phrase role="identifier">my_ec</phrase><phrase
  11624. role="special">]</phrase></code> to <code><phrase role="identifier">async_something</phrase><phrase
  11625. role="special">()</phrase></code> to bind a local <code><phrase role="identifier">error_code</phrase></code>
  11626. instance, then <code><phrase role="identifier">yield_handler_base</phrase><phrase
  11627. role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
  11628. role="special">()</phrase></code> stored its <code><phrase role="identifier">error_code</phrase></code>
  11629. to the caller&#8217;s <code><phrase role="identifier">my_ec</phrase></code>
  11630. instance, leaving <code><phrase role="identifier">async_result_base</phrase><phrase
  11631. role="special">::</phrase><phrase role="identifier">ec_</phrase></code>
  11632. initialized to success.
  11633. </simpara>
  11634. </listitem>
  11635. <listitem>
  11636. <simpara>
  11637. If the original caller passed <code><phrase role="identifier">yield</phrase></code>
  11638. to <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
  11639. without binding a local <code><phrase role="identifier">error_code</phrase></code>
  11640. variable, then <code><phrase role="identifier">yield_handler_base</phrase><phrase
  11641. role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
  11642. role="special">()</phrase></code> stored its <code><phrase role="identifier">error_code</phrase></code>
  11643. into <code><phrase role="identifier">async_result_base</phrase><phrase
  11644. role="special">::</phrase><phrase role="identifier">ec_</phrase></code>.
  11645. If in fact that <code><phrase role="identifier">error_code</phrase></code>
  11646. is success, then all is well.
  11647. </simpara>
  11648. </listitem>
  11649. <listitem>
  11650. <simpara>
  11651. Otherwise &mdash; the original caller did not bind a local <code><phrase role="identifier">error_code</phrase></code>
  11652. and <code><phrase role="identifier">yield_handler_base</phrase><phrase
  11653. role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
  11654. role="special">()</phrase></code> was called with an <code><phrase role="identifier">error_code</phrase></code>
  11655. indicating error &mdash; <code><phrase role="identifier">async_result_base</phrase><phrase
  11656. role="special">::</phrase><phrase role="identifier">get</phrase><phrase
  11657. role="special">()</phrase></code> throws <code><phrase role="identifier">system_error</phrase></code>
  11658. with that <code><phrase role="identifier">error_code</phrase></code>.
  11659. </simpara>
  11660. </listitem>
  11661. </itemizedlist>
  11662. <para>
  11663. The case in which <code><phrase role="identifier">async_something</phrase><phrase
  11664. role="special">()</phrase></code>&#8217;s completion callback has signature <code><phrase
  11665. role="keyword">void</phrase><phrase role="special">()</phrase></code> is
  11666. similar. <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
  11667. role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase
  11668. role="keyword">operator</phrase><phrase role="special">()()</phrase></code>
  11669. invokes the machinery above with a <quote>success</quote> <code><phrase role="identifier">error_code</phrase></code>.
  11670. </para>
  11671. <para>
  11672. A completion callback with signature <code><phrase role="keyword">void</phrase><phrase
  11673. role="special">(</phrase><phrase role="identifier">error_code</phrase><phrase
  11674. role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">)</phrase></code>
  11675. (that is: in addition to <code><phrase role="identifier">error_code</phrase></code>,
  11676. callback receives some data item) is handled somewhat differently. For this
  11677. kind of signature, <code><phrase role="identifier">handler_type</phrase><phrase
  11678. role="special">&lt;&gt;::</phrase><phrase role="identifier">type</phrase></code>
  11679. specifies <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
  11680. role="identifier">T</phrase><phrase role="special">&gt;</phrase></code> (for
  11681. <code><phrase role="identifier">T</phrase></code> other than <code><phrase
  11682. role="keyword">void</phrase></code>).
  11683. </para>
  11684. <para>
  11685. A <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
  11686. role="identifier">T</phrase><phrase role="special">&gt;</phrase></code> reserves
  11687. a <code><phrase role="identifier">value_</phrase></code> pointer to a value
  11688. of type <code><phrase role="identifier">T</phrase></code>:
  11689. </para>
  11690. <para>
  11691. <programlisting><phrase role="comment">// asio uses handler_type&lt;completion token type, signature&gt;::type to decide</phrase>
  11692. <phrase role="comment">// what to instantiate as the actual handler. Below, we specialize</phrase>
  11693. <phrase role="comment">// handler_type&lt; yield_t, ... &gt; to indicate yield_handler&lt;&gt;. So when you pass</phrase>
  11694. <phrase role="comment">// an instance of yield_t as an asio completion token, asio selects</phrase>
  11695. <phrase role="comment">// yield_handler&lt;&gt; as the actual handler class.</phrase>
  11696. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  11697. <phrase role="keyword">class</phrase> <phrase role="identifier">yield_handler</phrase><phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">{</phrase>
  11698. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  11699. <phrase role="comment">// asio passes the completion token to the handler constructor</phrase>
  11700. <phrase role="keyword">explicit</phrase> <phrase role="identifier">yield_handler</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">y</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
  11701. <phrase role="identifier">yield_handler_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">y</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
  11702. <phrase role="special">}</phrase>
  11703. <phrase role="comment">// completion callback passing only value (T)</phrase>
  11704. <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">t</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11705. <phrase role="comment">// just like callback passing success error_code</phrase>
  11706. <phrase role="special">(*</phrase><phrase role="keyword">this</phrase><phrase role="special">)(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase><phrase role="special">(),</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">t</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  11707. <phrase role="special">}</phrase>
  11708. <phrase role="comment">// completion callback passing (error_code, T)</phrase>
  11709. <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">t</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11710. <phrase role="identifier">BOOST_ASSERT_MSG</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_</phrase><phrase role="special">,</phrase>
  11711. <phrase role="string">&quot;Must inject value ptr &quot;</phrase>
  11712. <phrase role="string">&quot;before caling yield_handler&lt;T&gt;::operator()()&quot;</phrase><phrase role="special">);</phrase>
  11713. <phrase role="comment">// move the value to async_result&lt;&gt; instance BEFORE waking up a</phrase>
  11714. <phrase role="comment">// suspended fiber</phrase>
  11715. <phrase role="special">*</phrase> <phrase role="identifier">value_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">t</phrase><phrase role="special">);</phrase>
  11716. <phrase role="comment">// forward the call to base-class completion handler</phrase>
  11717. <phrase role="identifier">yield_handler_base</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase>
  11718. <phrase role="special">}</phrase>
  11719. <phrase role="comment">//private:</phrase>
  11720. <phrase role="comment">// pointer to destination for eventual value</phrase>
  11721. <phrase role="comment">// this must be injected by async_result before operator()() is called</phrase>
  11722. <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">value_</phrase><phrase role="special">{</phrase> <phrase role="keyword">nullptr</phrase> <phrase role="special">};</phrase>
  11723. <phrase role="special">};</phrase>
  11724. </programlisting>
  11725. </para>
  11726. <para>
  11727. This pointer is initialized to <code><phrase role="keyword">nullptr</phrase></code>.
  11728. </para>
  11729. <para>
  11730. When <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
  11731. instantiates <code><phrase role="identifier">async_result</phrase><phrase
  11732. role="special">&lt;</phrase><phrase role="identifier">yield_handler</phrase><phrase
  11733. role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;&gt;</phrase></code>:
  11734. </para>
  11735. <para>
  11736. <programlisting><phrase role="comment">// asio constructs an async_result&lt;&gt; instance from the yield_handler specified</phrase>
  11737. <phrase role="comment">// by handler_type&lt;&gt;::type. A particular asio async method constructs the</phrase>
  11738. <phrase role="comment">// yield_handler, constructs this async_result specialization from it, then</phrase>
  11739. <phrase role="comment">// returns the result of calling its get() method.</phrase>
  11740. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  11741. <phrase role="keyword">class</phrase> <phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">:</phrase>
  11742. <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase> <phrase role="special">{</phrase>
  11743. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  11744. <phrase role="comment">// type returned by get()</phrase>
  11745. <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
  11746. <phrase role="keyword">explicit</phrase> <phrase role="identifier">async_result</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">h</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
  11747. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">h</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
  11748. <phrase role="comment">// Inject ptr to our value_ member into yield_handler&lt;&gt;: result will</phrase>
  11749. <phrase role="comment">// be stored here.</phrase>
  11750. <phrase role="identifier">h</phrase><phrase role="special">.</phrase><phrase role="identifier">value_</phrase> <phrase role="special">=</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">value_</phrase><phrase role="special">;</phrase>
  11751. <phrase role="special">}</phrase>
  11752. <phrase role="comment">// asio async method returns result of calling get()</phrase>
  11753. <phrase role="identifier">type</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  11754. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
  11755. <phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_</phrase><phrase role="special">);</phrase>
  11756. <phrase role="special">}</phrase>
  11757. <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
  11758. <phrase role="identifier">type</phrase> <phrase role="identifier">value_</phrase><phrase role="special">{};</phrase>
  11759. <phrase role="special">};</phrase>
  11760. </programlisting>
  11761. </para>
  11762. <para>
  11763. this <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;&gt;</phrase></code>
  11764. specialization reserves a member of type <code><phrase role="identifier">T</phrase></code>
  11765. to receive the passed data item, and sets <code><phrase role="identifier">yield_handler</phrase><phrase
  11766. role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase
  11767. role="identifier">value_</phrase></code> to point to its own data member.
  11768. </para>
  11769. <para>
  11770. <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
  11771. role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
  11772. role="identifier">T</phrase><phrase role="special">&gt;&gt;</phrase></code>
  11773. overrides <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>.
  11774. The override calls <code><phrase role="identifier">async_result_base</phrase><phrase
  11775. role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>,
  11776. so the calling fiber suspends as described above.
  11777. </para>
  11778. <para>
  11779. <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
  11780. role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase
  11781. role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
  11782. role="identifier">error_code</phrase><phrase role="special">,</phrase> <phrase
  11783. role="identifier">T</phrase><phrase role="special">)</phrase></code> stores
  11784. its passed <code><phrase role="identifier">T</phrase></code> value into
  11785. <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
  11786. role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
  11787. role="identifier">T</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
  11788. role="identifier">value_</phrase></code>.
  11789. </para>
  11790. <para>
  11791. Then it passes control to <code><phrase role="identifier">yield_handler_base</phrase><phrase
  11792. role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
  11793. role="special">()(</phrase><phrase role="identifier">error_code</phrase><phrase
  11794. role="special">)</phrase></code> to deal with waking the original fiber as
  11795. described above.
  11796. </para>
  11797. <para>
  11798. When <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
  11799. role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
  11800. role="identifier">T</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
  11801. role="identifier">get</phrase><phrase role="special">()</phrase></code> resumes,
  11802. it returns the stored <code><phrase role="identifier">value_</phrase></code>
  11803. to <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
  11804. and ultimately to <code><phrase role="identifier">async_something</phrase><phrase
  11805. role="special">()</phrase></code>&#8217;s caller.
  11806. </para>
  11807. <para>
  11808. The case of a callback signature <code><phrase role="keyword">void</phrase><phrase
  11809. role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></code>
  11810. is handled by having <code><phrase role="identifier">yield_handler</phrase><phrase
  11811. role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase
  11812. role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
  11813. role="identifier">T</phrase><phrase role="special">)</phrase></code> engage
  11814. the <code><phrase role="keyword">void</phrase><phrase role="special">(</phrase><phrase
  11815. role="identifier">error_code</phrase><phrase role="special">,</phrase> <phrase
  11816. role="identifier">T</phrase><phrase role="special">)</phrase></code> machinery,
  11817. passing a <quote>success</quote> <code><phrase role="identifier">error_code</phrase></code>.
  11818. </para>
  11819. <para>
  11820. The source code above is found in <ulink url="../../examples/asio/yield.hpp">yield.hpp</ulink>
  11821. and <ulink url="../../examples/asio/detail/yield.hpp">detail/yield.hpp</ulink>.
  11822. </para>
  11823. </section>
  11824. </section>
  11825. <section id="fiber.nonblocking">
  11826. <title><anchor id="nonblocking"/><link linkend="fiber.nonblocking">Integrating
  11827. Fibers with Nonblocking I/O</link></title>
  11828. <bridgehead renderas="sect3" id="fiber.nonblocking.h0">
  11829. <phrase id="fiber.nonblocking.overview"/><link linkend="fiber.nonblocking.overview">Overview</link>
  11830. </bridgehead>
  11831. <para>
  11832. <emphasis>Nonblocking</emphasis> I/O is distinct from <emphasis>asynchronous</emphasis>
  11833. I/O. A true async I/O operation promises to initiate the operation and notify
  11834. the caller on completion, usually via some sort of callback (as described in
  11835. <link linkend="callbacks">Integrating Fibers with Asynchronous Callbacks</link>).
  11836. </para>
  11837. <para>
  11838. In contrast, a nonblocking I/O operation refuses to start at all if it would
  11839. be necessary to block, returning an error code such as <ulink url="http://man7.org/linux/man-pages/man3/errno.3.html"><code><phrase
  11840. role="identifier">EWOULDBLOCK</phrase></code></ulink>. The operation is performed
  11841. only when it can complete immediately. In effect, the caller must repeatedly
  11842. retry the operation until it stops returning <code><phrase role="identifier">EWOULDBLOCK</phrase></code>.
  11843. </para>
  11844. <para>
  11845. In a classic event-driven program, it can be something of a headache to use
  11846. nonblocking I/O. At the point where the nonblocking I/O is attempted, a return
  11847. value of <code><phrase role="identifier">EWOULDBLOCK</phrase></code> requires
  11848. the caller to pass control back to the main event loop, arranging to retry
  11849. again on the next iteration.
  11850. </para>
  11851. <para>
  11852. Worse, a nonblocking I/O operation might <emphasis>partially</emphasis> succeed.
  11853. That means that the relevant business logic must continue receiving control
  11854. on every main loop iteration until all required data have been processed: a
  11855. doubly-nested loop, implemented as a callback-driven state machine.
  11856. </para>
  11857. <para>
  11858. <emphasis role="bold">Boost.Fiber</emphasis> can simplify this problem immensely.
  11859. Once you have integrated with the application's main loop as described in
  11860. <link linkend="integration">Sharing a Thread with Another Main Loop</link>,
  11861. waiting for the next main-loop iteration is as simple as calling <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>.
  11862. </para>
  11863. <bridgehead renderas="sect3" id="fiber.nonblocking.h1">
  11864. <phrase id="fiber.nonblocking.example_nonblocking_api"/><link linkend="fiber.nonblocking.example_nonblocking_api">Example
  11865. Nonblocking API</link>
  11866. </bridgehead>
  11867. <para>
  11868. For purposes of illustration, consider this API:
  11869. </para>
  11870. <para>
  11871. <programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">{</phrase>
  11872. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  11873. <phrase role="identifier">NonblockingAPI</phrase><phrase role="special">();</phrase>
  11874. <phrase role="comment">// nonblocking operation: may return EWOULDBLOCK</phrase>
  11875. <phrase role="keyword">int</phrase> <phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">desired</phrase><phrase role="special">);</phrase>
  11876. <phrase role="special">...</phrase>
  11877. <phrase role="special">};</phrase>
  11878. </programlisting>
  11879. </para>
  11880. <bridgehead renderas="sect3" id="fiber.nonblocking.h2">
  11881. <phrase id="fiber.nonblocking.polling_for_completion"/><link linkend="fiber.nonblocking.polling_for_completion">Polling
  11882. for Completion</link>
  11883. </bridgehead>
  11884. <para>
  11885. We can build a low-level wrapper around <code><phrase role="identifier">NonblockingAPI</phrase><phrase
  11886. role="special">::</phrase><phrase role="identifier">read</phrase><phrase role="special">()</phrase></code>
  11887. that shields its caller from ever having to deal with <code><phrase role="identifier">EWOULDBLOCK</phrase></code>:
  11888. </para>
  11889. <para>
  11890. <programlisting><phrase role="comment">// guaranteed not to return EWOULDBLOCK</phrase>
  11891. <phrase role="keyword">int</phrase> <phrase role="identifier">read_chunk</phrase><phrase role="special">(</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11892. <phrase role="keyword">int</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase>
  11893. <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">EWOULDBLOCK</phrase> <phrase role="special">==</phrase> <phrase role="special">(</phrase> <phrase role="identifier">error</phrase> <phrase role="special">=</phrase> <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11894. <phrase role="comment">// not ready yet -- try again on the next iteration of the</phrase>
  11895. <phrase role="comment">// application's main loop</phrase>
  11896. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
  11897. <phrase role="special">}</phrase>
  11898. <phrase role="keyword">return</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase>
  11899. <phrase role="special">}</phrase>
  11900. </programlisting>
  11901. </para>
  11902. <bridgehead renderas="sect3" id="fiber.nonblocking.h3">
  11903. <phrase id="fiber.nonblocking.filling_all_desired_data"/><link linkend="fiber.nonblocking.filling_all_desired_data">Filling
  11904. All Desired Data</link>
  11905. </bridgehead>
  11906. <para>
  11907. Given <code><phrase role="identifier">read_chunk</phrase><phrase role="special">()</phrase></code>,
  11908. we can straightforwardly iterate until we have all desired data:
  11909. </para>
  11910. <para>
  11911. <programlisting><phrase role="comment">// keep reading until desired length, EOF or error</phrase>
  11912. <phrase role="comment">// may return both partial data and nonzero error</phrase>
  11913. <phrase role="keyword">int</phrase> <phrase role="identifier">read_desired</phrase><phrase role="special">(</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11914. <phrase role="comment">// we're going to accumulate results into 'data'</phrase>
  11915. <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">clear</phrase><phrase role="special">();</phrase>
  11916. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">chunk</phrase><phrase role="special">;</phrase>
  11917. <phrase role="keyword">int</phrase> <phrase role="identifier">error</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  11918. <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">length</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">desired</phrase> <phrase role="special">&amp;&amp;</phrase>
  11919. <phrase role="special">(</phrase> <phrase role="identifier">error</phrase> <phrase role="special">=</phrase> <phrase role="identifier">read_chunk</phrase><phrase role="special">(</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">chunk</phrase><phrase role="special">,</phrase> <phrase role="identifier">desired</phrase> <phrase role="special">-</phrase> <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">length</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">==</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11920. <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">append</phrase><phrase role="special">(</phrase> <phrase role="identifier">chunk</phrase><phrase role="special">);</phrase>
  11921. <phrase role="special">}</phrase>
  11922. <phrase role="keyword">return</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase>
  11923. <phrase role="special">}</phrase>
  11924. </programlisting>
  11925. </para>
  11926. <para>
  11927. (Of <emphasis>course</emphasis> there are more efficient ways to accumulate
  11928. string data. That's not the point of this example.)
  11929. </para>
  11930. <bridgehead renderas="sect3" id="fiber.nonblocking.h4">
  11931. <phrase id="fiber.nonblocking.wrapping_it_up"/><link linkend="fiber.nonblocking.wrapping_it_up">Wrapping
  11932. it Up</link>
  11933. </bridgehead>
  11934. <para>
  11935. Finally, we can define a relevant exception:
  11936. </para>
  11937. <para>
  11938. <programlisting><phrase role="comment">// exception class augmented with both partially-read data and errorcode</phrase>
  11939. <phrase role="keyword">class</phrase> <phrase role="identifier">IncompleteRead</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase> <phrase role="special">{</phrase>
  11940. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  11941. <phrase role="identifier">IncompleteRead</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">what</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">partial</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
  11942. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">(</phrase> <phrase role="identifier">what</phrase><phrase role="special">),</phrase>
  11943. <phrase role="identifier">partial_</phrase><phrase role="special">(</phrase> <phrase role="identifier">partial</phrase><phrase role="special">),</phrase>
  11944. <phrase role="identifier">ec_</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11945. <phrase role="special">}</phrase>
  11946. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">get_partial</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
  11947. <phrase role="keyword">return</phrase> <phrase role="identifier">partial_</phrase><phrase role="special">;</phrase>
  11948. <phrase role="special">}</phrase>
  11949. <phrase role="keyword">int</phrase> <phrase role="identifier">get_errorcode</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
  11950. <phrase role="keyword">return</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase>
  11951. <phrase role="special">}</phrase>
  11952. <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
  11953. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">partial_</phrase><phrase role="special">;</phrase>
  11954. <phrase role="keyword">int</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase>
  11955. <phrase role="special">};</phrase>
  11956. </programlisting>
  11957. </para>
  11958. <para>
  11959. and write a simple <code><phrase role="identifier">read</phrase><phrase role="special">()</phrase></code>
  11960. function that either returns all desired data or throws <code><phrase role="identifier">IncompleteRead</phrase></code>:
  11961. </para>
  11962. <para>
  11963. <programlisting><phrase role="comment">// read all desired data or throw IncompleteRead</phrase>
  11964. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11965. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">data</phrase><phrase role="special">;</phrase>
  11966. <phrase role="keyword">int</phrase> <phrase role="identifier">ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">read_desired</phrase><phrase role="special">(</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  11967. <phrase role="comment">// for present purposes, EOF isn't a failure</phrase>
  11968. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">ec</phrase> <phrase role="special">||</phrase> <phrase role="identifier">EOF</phrase> <phrase role="special">==</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  11969. <phrase role="keyword">return</phrase> <phrase role="identifier">data</phrase><phrase role="special">;</phrase>
  11970. <phrase role="special">}</phrase>
  11971. <phrase role="comment">// oh oh, partial read</phrase>
  11972. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">msg</phrase><phrase role="special">;</phrase>
  11973. <phrase role="identifier">msg</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;NonblockingAPI::read() error &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">ec</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; after &quot;</phrase>
  11974. <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">length</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; of &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">desired</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; characters&quot;</phrase><phrase role="special">;</phrase>
  11975. <phrase role="keyword">throw</phrase> <phrase role="identifier">IncompleteRead</phrase><phrase role="special">(</phrase> <phrase role="identifier">msg</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">(),</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase>
  11976. <phrase role="special">}</phrase>
  11977. </programlisting>
  11978. </para>
  11979. <para>
  11980. Once we can transparently wait for the next main-loop iteration using <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>,
  11981. ordinary encapsulation Just Works.
  11982. </para>
  11983. <para>
  11984. The source code above is found in <ulink url="../../examples/adapt_nonblocking.cpp">adapt_nonblocking.cpp</ulink>.
  11985. </para>
  11986. </section>
  11987. <section id="fiber.when_any">
  11988. <title><anchor id="when_any"/><link linkend="fiber.when_any">when_any / when_all
  11989. functionality</link></title>
  11990. <bridgehead renderas="sect3" id="fiber.when_any.h0">
  11991. <phrase id="fiber.when_any.overview"/><link linkend="fiber.when_any.overview">Overview</link>
  11992. </bridgehead>
  11993. <para>
  11994. A bit of wisdom from the early days of computing still holds true today: prefer
  11995. to model program state using the instruction pointer rather than with Boolean
  11996. flags. In other words, if the program must <quote>do something</quote> and
  11997. then do something almost the same, but with minor changes... perhaps parts
  11998. of that something should be broken out as smaller separate functions, rather
  11999. than introducing flags to alter the internal behavior of a monolithic function.
  12000. </para>
  12001. <para>
  12002. To that we would add: prefer to describe control flow using C++ native constructs
  12003. such as function calls, <code><phrase role="keyword">if</phrase></code>, <code><phrase
  12004. role="keyword">while</phrase></code>, <code><phrase role="keyword">for</phrase></code>,
  12005. <code><phrase role="keyword">do</phrase></code> et al. rather than as chains
  12006. of callbacks.
  12007. </para>
  12008. <para>
  12009. One of the great strengths of <emphasis role="bold">Boost.Fiber</emphasis>
  12010. is the flexibility it confers on the coder to restructure an application from
  12011. chains of callbacks to straightforward C++ statement sequence, even when code
  12012. in that fiber is in fact interleaved with code running in other fibers.
  12013. </para>
  12014. <para>
  12015. There has been much recent discussion about the benefits of when_any and when_all
  12016. functionality. When dealing with asynchronous and possibly unreliable services,
  12017. these are valuable idioms. But of course when_any and when_all are closely
  12018. tied to the use of chains of callbacks.
  12019. </para>
  12020. <para>
  12021. This section presents recipes for achieving the same ends, in the context of
  12022. a fiber that wants to <quote>do something</quote> when one or more other independent
  12023. activities have completed. Accordingly, these are <code><phrase role="identifier">wait_something</phrase><phrase
  12024. role="special">()</phrase></code> functions rather than <code><phrase role="identifier">when_something</phrase><phrase
  12025. role="special">()</phrase></code> functions. The expectation is that the calling
  12026. fiber asks to launch those independent activities, then waits for them, then
  12027. sequentially proceeds with whatever processing depends on those results.
  12028. </para>
  12029. <para>
  12030. The function names shown (e.g. <link linkend="wait_first_simple"><code><phrase
  12031. role="identifier">wait_first_simple</phrase><phrase role="special">()</phrase></code></link>)
  12032. are for illustrative purposes only, because all these functions have been bundled
  12033. into a single source file. Presumably, if (say) <link linkend="wait_first_success"><code><phrase
  12034. role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link>
  12035. best suits your application needs, you could introduce that variant with the
  12036. name <code><phrase role="identifier">wait_any</phrase><phrase role="special">()</phrase></code>.
  12037. </para>
  12038. <note>
  12039. <para>
  12040. The functions presented in this section accept variadic argument lists of
  12041. task functions. Corresponding <code><phrase role="identifier">wait_something</phrase><phrase
  12042. role="special">()</phrase></code> functions accepting a container of task
  12043. functions are left as an exercise for the interested reader. Those should
  12044. actually be simpler. Most of the complexity would arise from overloading
  12045. the same name for both purposes.
  12046. </para>
  12047. </note>
  12048. <para>
  12049. All the source code for this section is found in <ulink url="../../examples/wait_stuff.cpp">wait_stuff.cpp</ulink>.
  12050. </para>
  12051. <bridgehead renderas="sect3" id="fiber.when_any.h1">
  12052. <phrase id="fiber.when_any.example_task_function"/><link linkend="fiber.when_any.example_task_function">Example
  12053. Task Function</link>
  12054. </bridgehead>
  12055. <para>
  12056. <anchor id="wait_sleeper"/>We found it convenient to model an asynchronous
  12057. task using this function:
  12058. </para>
  12059. <para>
  12060. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  12061. <phrase role="identifier">T</phrase> <phrase role="identifier">sleeper_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">item</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">ms</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">thrw</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12062. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">descb</phrase><phrase role="special">,</phrase> <phrase role="identifier">funcb</phrase><phrase role="special">;</phrase>
  12063. <phrase role="identifier">descb</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">item</phrase><phrase role="special">;</phrase>
  12064. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">desc</phrase><phrase role="special">(</phrase> <phrase role="identifier">descb</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  12065. <phrase role="identifier">funcb</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; sleeper(&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">item</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;)&quot;</phrase><phrase role="special">;</phrase>
  12066. <phrase role="identifier">Verbose</phrase> <phrase role="identifier">v</phrase><phrase role="special">(</phrase> <phrase role="identifier">funcb</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  12067. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">sleep_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">milliseconds</phrase><phrase role="special">(</phrase> <phrase role="identifier">ms</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12068. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">thrw</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12069. <phrase role="keyword">throw</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">(</phrase> <phrase role="identifier">desc</phrase><phrase role="special">);</phrase>
  12070. <phrase role="special">}</phrase>
  12071. <phrase role="keyword">return</phrase> <phrase role="identifier">item</phrase><phrase role="special">;</phrase>
  12072. <phrase role="special">}</phrase>
  12073. </programlisting>
  12074. </para>
  12075. <para>
  12076. with type-specific <code><phrase role="identifier">sleeper</phrase><phrase
  12077. role="special">()</phrase></code> <quote>front ends</quote> for <code><phrase
  12078. role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase></code>,
  12079. <code><phrase role="keyword">double</phrase></code> and <code><phrase role="keyword">int</phrase></code>.
  12080. </para>
  12081. <para>
  12082. <code><phrase role="identifier">Verbose</phrase></code> simply prints a message
  12083. to <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  12084. role="identifier">cout</phrase></code> on construction and destruction.
  12085. </para>
  12086. <para>
  12087. Basically:
  12088. </para>
  12089. <orderedlist>
  12090. <listitem>
  12091. <simpara>
  12092. <code><phrase role="identifier">sleeper</phrase><phrase role="special">()</phrase></code>
  12093. prints a start message;
  12094. </simpara>
  12095. </listitem>
  12096. <listitem>
  12097. <simpara>
  12098. sleeps for the specified number of milliseconds;
  12099. </simpara>
  12100. </listitem>
  12101. <listitem>
  12102. <simpara>
  12103. if <code><phrase role="identifier">thrw</phrase></code> is passed as <code><phrase
  12104. role="keyword">true</phrase></code>, throws a string description of the
  12105. passed <code><phrase role="identifier">item</phrase></code>;
  12106. </simpara>
  12107. </listitem>
  12108. <listitem>
  12109. <simpara>
  12110. else returns the passed <code><phrase role="identifier">item</phrase></code>.
  12111. </simpara>
  12112. </listitem>
  12113. <listitem>
  12114. <simpara>
  12115. On the way out, <code><phrase role="identifier">sleeper</phrase><phrase
  12116. role="special">()</phrase></code> produces a stop message.
  12117. </simpara>
  12118. </listitem>
  12119. </orderedlist>
  12120. <para>
  12121. This function will feature in the example calls to the various functions presented
  12122. below.
  12123. </para>
  12124. <section id="fiber.when_any.when_any">
  12125. <title><link linkend="fiber.when_any.when_any">when_any</link></title>
  12126. <section id="fiber.when_any.when_any.when_any__simple_completion">
  12127. <title><anchor id="wait_first_simple_section"/><link linkend="fiber.when_any.when_any.when_any__simple_completion">when_any,
  12128. simple completion</link></title>
  12129. <para>
  12130. The simplest case is when you only need to know that the first of a set
  12131. of asynchronous tasks has completed &mdash; but you don't need to obtain a return
  12132. value, and you're confident that they will not throw exceptions.
  12133. </para>
  12134. <para>
  12135. <anchor id="wait_done"/>For this we introduce a <code><phrase role="identifier">Done</phrase></code>
  12136. class to wrap a <code><phrase role="keyword">bool</phrase></code> variable
  12137. with a <link linkend="class_condition_variable"><code>condition_variable</code></link> and a <link linkend="class_mutex"><code>mutex</code></link>:
  12138. </para>
  12139. <para>
  12140. <programlisting><phrase role="comment">// Wrap canonical pattern for condition_variable + bool flag</phrase>
  12141. <phrase role="keyword">struct</phrase> <phrase role="identifier">Done</phrase> <phrase role="special">{</phrase>
  12142. <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
  12143. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase> <phrase role="identifier">cond</phrase><phrase role="special">;</phrase>
  12144. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="identifier">mutex</phrase><phrase role="special">;</phrase>
  12145. <phrase role="keyword">bool</phrase> <phrase role="identifier">ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
  12146. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  12147. <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Done</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">ptr</phrase><phrase role="special">;</phrase>
  12148. <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  12149. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lock</phrase><phrase role="special">(</phrase> <phrase role="identifier">mutex</phrase><phrase role="special">);</phrase>
  12150. <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lock</phrase><phrase role="special">,</phrase> <phrase role="special">[</phrase><phrase role="keyword">this</phrase><phrase role="special">](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">ready</phrase><phrase role="special">;</phrase> <phrase role="special">});</phrase>
  12151. <phrase role="special">}</phrase>
  12152. <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  12153. <phrase role="special">{</phrase>
  12154. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lock</phrase><phrase role="special">(</phrase> <phrase role="identifier">mutex</phrase><phrase role="special">);</phrase>
  12155. <phrase role="identifier">ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
  12156. <phrase role="special">}</phrase> <phrase role="comment">// release mutex</phrase>
  12157. <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase>
  12158. <phrase role="special">}</phrase>
  12159. <phrase role="special">};</phrase>
  12160. </programlisting>
  12161. </para>
  12162. <para>
  12163. The pattern we follow throughout this section is to pass a <ulink url="http://www.cplusplus.com/reference/memory/shared_ptr/"><code><phrase
  12164. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  12165. role="identifier">shared_ptr</phrase><phrase role="special">&lt;&gt;</phrase></code></ulink>
  12166. to the relevant synchronization object to the various tasks' fiber functions.
  12167. This eliminates nagging questions about the lifespan of the synchronization
  12168. object relative to the last of the fibers.
  12169. </para>
  12170. <para>
  12171. <anchor id="wait_first_simple"/><code><phrase role="identifier">wait_first_simple</phrase><phrase
  12172. role="special">()</phrase></code> uses that tactic for <link linkend="wait_done"><code><phrase
  12173. role="identifier">Done</phrase></code></link>:
  12174. </para>
  12175. <para>
  12176. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  12177. <phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_simple</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12178. <phrase role="comment">// Use shared_ptr because each function's fiber will bind it separately,</phrase>
  12179. <phrase role="comment">// and we're going to return before the last of them completes.</phrase>
  12180. <phrase role="keyword">auto</phrase> <phrase role="identifier">done</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Done</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
  12181. <phrase role="identifier">wait_first_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">done</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
  12182. <phrase role="identifier">done</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
  12183. <phrase role="special">}</phrase>
  12184. </programlisting>
  12185. </para>
  12186. <para>
  12187. <anchor id="wait_first_simple_impl"/><code><phrase role="identifier">wait_first_simple_impl</phrase><phrase
  12188. role="special">()</phrase></code> is an ordinary recursion over the argument
  12189. pack, capturing <code><phrase role="identifier">Done</phrase><phrase role="special">::</phrase><phrase
  12190. role="identifier">ptr</phrase></code> for each new fiber:
  12191. </para>
  12192. <para>
  12193. <programlisting><phrase role="comment">// Degenerate case: when there are no functions to wait for, return</phrase>
  12194. <phrase role="comment">// immediately.</phrase>
  12195. <phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">Done</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12196. <phrase role="special">}</phrase>
  12197. <phrase role="comment">// When there's at least one function to wait for, launch it and recur to</phrase>
  12198. <phrase role="comment">// process the rest.</phrase>
  12199. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  12200. <phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">Done</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr</phrase> <phrase role="identifier">done</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12201. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">done</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase>
  12202. <phrase role="identifier">function</phrase><phrase role="special">();</phrase>
  12203. <phrase role="identifier">done</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">notify</phrase><phrase role="special">();</phrase>
  12204. <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
  12205. <phrase role="identifier">wait_first_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">done</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
  12206. <phrase role="special">}</phrase>
  12207. </programlisting>
  12208. </para>
  12209. <para>
  12210. The body of the fiber's lambda is extremely simple, as promised: call the
  12211. function, notify <link linkend="wait_done"><code><phrase role="identifier">Done</phrase></code></link>
  12212. when it returns. The first fiber to do so allows <code><phrase role="identifier">wait_first_simple</phrase><phrase
  12213. role="special">()</phrase></code> to return &mdash; which is why it's useful to
  12214. have <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  12215. role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase><phrase
  12216. role="identifier">Done</phrase><phrase role="special">&gt;</phrase></code>
  12217. manage the lifespan of our <code><phrase role="identifier">Done</phrase></code>
  12218. object rather than declaring it as a stack variable in <code><phrase role="identifier">wait_first_simple</phrase><phrase
  12219. role="special">()</phrase></code>.
  12220. </para>
  12221. <para>
  12222. This is how you might call it:
  12223. </para>
  12224. <para>
  12225. <programlisting><phrase role="identifier">wait_first_simple</phrase><phrase role="special">(</phrase>
  12226. <phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfs_long&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12227. <phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfs_medium&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12228. <phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfs_short&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
  12229. </programlisting>
  12230. </para>
  12231. <para>
  12232. In this example, control resumes after <code><phrase role="identifier">wait_first_simple</phrase><phrase
  12233. role="special">()</phrase></code> when <link linkend="wait_sleeper"><code><phrase
  12234. role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase
  12235. role="string">&quot;wfs_short&quot;</phrase><phrase role="special">,</phrase>
  12236. <phrase role="number">50</phrase><phrase role="special">)</phrase></code></link>
  12237. completes &mdash; even though the other two <code><phrase role="identifier">sleeper</phrase><phrase
  12238. role="special">()</phrase></code> fibers are still running.
  12239. </para>
  12240. </section>
  12241. <section id="fiber.when_any.when_any.when_any__return_value">
  12242. <title><link linkend="fiber.when_any.when_any.when_any__return_value">when_any,
  12243. return value</link></title>
  12244. <para>
  12245. It seems more useful to add the ability to capture the return value from
  12246. the first of the task functions to complete. Again, we assume that none
  12247. will throw an exception.
  12248. </para>
  12249. <para>
  12250. One tactic would be to adapt our <link linkend="wait_done"><code><phrase
  12251. role="identifier">Done</phrase></code></link> class to store the first
  12252. of the return values, rather than a simple <code><phrase role="keyword">bool</phrase></code>.
  12253. However, we choose instead to use a <link linkend="class_buffered_channel"><code>buffered_channel&lt;&gt;</code></link>.
  12254. We'll only need to enqueue the first value, so we'll <link linkend="buffered_channel_close"><code>buffered_channel::close()</code></link> it
  12255. once we've retrieved that value. Subsequent <code><phrase role="identifier">push</phrase><phrase
  12256. role="special">()</phrase></code> calls will return <code><phrase role="identifier">closed</phrase></code>.
  12257. </para>
  12258. <para>
  12259. <anchor id="wait_first_value"/>
  12260. <programlisting><phrase role="comment">// Assume that all passed functions have the same return type. The return type</phrase>
  12261. <phrase role="comment">// of wait_first_value() is the return type of the first passed function. It is</phrase>
  12262. <phrase role="comment">// simply invalid to pass NO functions.</phrase>
  12263. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  12264. <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase>
  12265. <phrase role="identifier">wait_first_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12266. <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
  12267. <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
  12268. <phrase role="keyword">auto</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="number">64</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12269. <phrase role="comment">// launch all the relevant fibers</phrase>
  12270. <phrase role="identifier">wait_first_value_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">,</phrase>
  12271. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
  12272. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
  12273. <phrase role="comment">// retrieve the first value</phrase>
  12274. <phrase role="identifier">return_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  12275. <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
  12276. <phrase role="identifier">chanp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
  12277. <phrase role="keyword">return</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
  12278. <phrase role="special">}</phrase>
  12279. </programlisting>
  12280. </para>
  12281. <para>
  12282. <anchor id="wait_first_value_impl"/>The meat of the <code><phrase role="identifier">wait_first_value_impl</phrase><phrase
  12283. role="special">()</phrase></code> function is as you might expect:
  12284. </para>
  12285. <para>
  12286. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;</phrase>
  12287. <phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_value_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">,</phrase>
  12288. <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12289. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">chan</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase>
  12290. <phrase role="comment">// Ignore channel_op_status returned by push():</phrase>
  12291. <phrase role="comment">// might be closed; we simply don't care.</phrase>
  12292. <phrase role="identifier">chan</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">function</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  12293. <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
  12294. <phrase role="special">}</phrase>
  12295. </programlisting>
  12296. </para>
  12297. <para>
  12298. It calls the passed function, pushes its return value and ignores the
  12299. <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>
  12300. result. You might call it like this:
  12301. </para>
  12302. <para>
  12303. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_value</phrase><phrase role="special">(</phrase>
  12304. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfv_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12305. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfv_second&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12306. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfv_first&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
  12307. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;wait_first_value() =&gt; &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">result</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  12308. <phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">result</phrase> <phrase role="special">==</phrase> <phrase role="string">&quot;wfv_first&quot;</phrase><phrase role="special">);</phrase>
  12309. </programlisting>
  12310. </para>
  12311. </section>
  12312. <section id="fiber.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception">
  12313. <title><link linkend="fiber.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception">when_any,
  12314. produce first outcome, whether result or exception</link></title>
  12315. <para>
  12316. We may not be running in an environment in which we can guarantee no exception
  12317. will be thrown by any of our task functions. In that case, the above implementations
  12318. of <code><phrase role="identifier">wait_first_something</phrase><phrase
  12319. role="special">()</phrase></code> would be naïve: as mentioned in <link
  12320. linkend="exceptions">the section on Fiber Management</link>, an uncaught
  12321. exception in one of our task fibers would cause <code><phrase role="identifier">std</phrase><phrase
  12322. role="special">::</phrase><phrase role="identifier">terminate</phrase><phrase
  12323. role="special">()</phrase></code> to be called.
  12324. </para>
  12325. <para>
  12326. Let's at least ensure that such an exception would propagate to the fiber
  12327. awaiting the first result. We can use <link linkend="class_future"><code>future&lt;&gt;</code></link> to transport
  12328. either a return value or an exception. Therefore, we will change <link
  12329. linkend="wait_first_value"><code><phrase role="identifier">wait_first_value</phrase><phrase
  12330. role="special">()</phrase></code></link>'s <link linkend="class_buffered_channel"><code>buffered_channel&lt;&gt;</code></link> to
  12331. hold <code><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
  12332. <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code>
  12333. items instead of simply <code><phrase role="identifier">T</phrase></code>.
  12334. </para>
  12335. <para>
  12336. Once we have a <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
  12337. in hand, all we need do is call <link linkend="future_get"><code>future::get()</code></link>, which will either
  12338. return the value or rethrow the exception.
  12339. </para>
  12340. <para>
  12341. <anchor id="wait_first_outcome"/>
  12342. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  12343. <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase>
  12344. <phrase role="identifier">wait_first_outcome</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12345. <phrase role="comment">// In this case, the value we pass through the channel is actually a</phrase>
  12346. <phrase role="comment">// future -- which is already ready. future can carry either a value or an</phrase>
  12347. <phrase role="comment">// exception.</phrase>
  12348. <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
  12349. <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase>
  12350. <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
  12351. <phrase role="keyword">auto</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="number">64</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12352. <phrase role="comment">// launch all the relevant fibers</phrase>
  12353. <phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">,</phrase>
  12354. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
  12355. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
  12356. <phrase role="comment">// retrieve the first future</phrase>
  12357. <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  12358. <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
  12359. <phrase role="identifier">chanp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
  12360. <phrase role="comment">// either return value or throw exception</phrase>
  12361. <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
  12362. <phrase role="special">}</phrase>
  12363. </programlisting>
  12364. </para>
  12365. <para>
  12366. So far so good &mdash; but there's a timing issue. How should we obtain the <code><phrase
  12367. role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
  12368. to <link linkend="buffered_channel_push"><code>buffered_channel::push()</code></link> on the queue?
  12369. </para>
  12370. <para>
  12371. We could call <link linkend="fibers_async"><code>fibers::async()</code></link>. That would certainly produce
  12372. a <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
  12373. for the task function. The trouble is that it would return too quickly!
  12374. We only want <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
  12375. items for <emphasis>completed</emphasis> tasks on our <code><phrase role="identifier">queue</phrase><phrase
  12376. role="special">&lt;&gt;</phrase></code>. In fact, we only want the <code><phrase
  12377. role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
  12378. for the one that completes first. If each fiber launched by <code><phrase
  12379. role="identifier">wait_first_outcome</phrase><phrase role="special">()</phrase></code>
  12380. were to <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>
  12381. the result of calling <code><phrase role="identifier">async</phrase><phrase
  12382. role="special">()</phrase></code>, the queue would only ever report the
  12383. result of the leftmost task item &mdash; <emphasis>not</emphasis> the one that
  12384. completes most quickly.
  12385. </para>
  12386. <para>
  12387. Calling <link linkend="future_get"><code>future::get()</code></link> on the future returned by <code><phrase
  12388. role="identifier">async</phrase><phrase role="special">()</phrase></code>
  12389. wouldn't be right. You can only call <code><phrase role="identifier">get</phrase><phrase
  12390. role="special">()</phrase></code> once per <code><phrase role="identifier">future</phrase><phrase
  12391. role="special">&lt;&gt;</phrase></code> instance! And if there were an
  12392. exception, it would be rethrown inside the helper fiber at the producer
  12393. end of the queue, rather than propagated to the consumer end.
  12394. </para>
  12395. <para>
  12396. We could call <link linkend="future_wait"><code>future::wait()</code></link>. That would block the helper fiber
  12397. until the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
  12398. became ready, at which point we could <code><phrase role="identifier">push</phrase><phrase
  12399. role="special">()</phrase></code> it to be retrieved by <code><phrase role="identifier">wait_first_outcome</phrase><phrase
  12400. role="special">()</phrase></code>.
  12401. </para>
  12402. <para>
  12403. That would work &mdash; but there's a simpler tactic that avoids creating an extra
  12404. fiber. We can wrap the task function in a <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link>.
  12405. While one naturally thinks of passing a <code><phrase role="identifier">packaged_task</phrase><phrase
  12406. role="special">&lt;&gt;</phrase></code> to a new fiber &mdash; that is, in fact,
  12407. what <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code>
  12408. does &mdash; in this case, we're already running in the helper fiber at the producer
  12409. end of the queue! We can simply <emphasis>call</emphasis> the <code><phrase
  12410. role="identifier">packaged_task</phrase><phrase role="special">&lt;&gt;</phrase></code>.
  12411. On return from that call, the task function has completed, meaning that
  12412. the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
  12413. obtained from the <code><phrase role="identifier">packaged_task</phrase><phrase
  12414. role="special">&lt;&gt;</phrase></code> is certain to be ready. At that
  12415. point we can simply <code><phrase role="identifier">push</phrase><phrase
  12416. role="special">()</phrase></code> it to the queue.
  12417. </para>
  12418. <para>
  12419. <anchor id="wait_first_outcome_impl"/>
  12420. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">CHANP</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;</phrase>
  12421. <phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">CHANP</phrase> <phrase role="identifier">chan</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12422. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase>
  12423. <phrase role="comment">// Use std::bind() here for C++11 compatibility. C++11 lambda capture</phrase>
  12424. <phrase role="comment">// can't move a move-only Fn type, but bind() can. Let bind() move the</phrase>
  12425. <phrase role="comment">// channel pointer and the function into the bound object, passing</phrase>
  12426. <phrase role="comment">// references into the lambda.</phrase>
  12427. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
  12428. <phrase role="special">[](</phrase> <phrase role="identifier">CHANP</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">,</phrase>
  12429. <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12430. <phrase role="comment">// Instantiate a packaged_task to capture any exception thrown by</phrase>
  12431. <phrase role="comment">// function.</phrase>
  12432. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">task</phrase><phrase role="special">(</phrase> <phrase role="identifier">function</phrase><phrase role="special">);</phrase>
  12433. <phrase role="comment">// Immediately run this packaged_task on same fiber. We want</phrase>
  12434. <phrase role="comment">// function() to have completed BEFORE we push the future.</phrase>
  12435. <phrase role="identifier">task</phrase><phrase role="special">();</phrase>
  12436. <phrase role="comment">// Pass the corresponding future to consumer. Ignore</phrase>
  12437. <phrase role="comment">// channel_op_status returned by push(): might be closed; we</phrase>
  12438. <phrase role="comment">// simply don't care.</phrase>
  12439. <phrase role="identifier">chan</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">task</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  12440. <phrase role="special">},</phrase>
  12441. <phrase role="identifier">chan</phrase><phrase role="special">,</phrase>
  12442. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase>
  12443. <phrase role="special">)).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
  12444. <phrase role="special">}</phrase>
  12445. </programlisting>
  12446. </para>
  12447. <para>
  12448. Calling it might look like this:
  12449. </para>
  12450. <para>
  12451. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_outcome</phrase><phrase role="special">(</phrase>
  12452. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfos_first&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12453. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfos_second&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12454. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfos_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
  12455. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;wait_first_outcome(success) =&gt; &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">result</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  12456. <phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">result</phrase> <phrase role="special">==</phrase> <phrase role="string">&quot;wfos_first&quot;</phrase><phrase role="special">);</phrase>
  12457. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">thrown</phrase><phrase role="special">;</phrase>
  12458. <phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
  12459. <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_outcome</phrase><phrase role="special">(</phrase>
  12460. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfof_first&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">,</phrase> <phrase role="keyword">true</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12461. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfof_second&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12462. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfof_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
  12463. <phrase role="special">}</phrase> <phrase role="keyword">catch</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">e</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12464. <phrase role="identifier">thrown</phrase> <phrase role="special">=</phrase> <phrase role="identifier">e</phrase><phrase role="special">.</phrase><phrase role="identifier">what</phrase><phrase role="special">();</phrase>
  12465. <phrase role="special">}</phrase>
  12466. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;wait_first_outcome(fail) threw '&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">thrown</phrase>
  12467. <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;'&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  12468. <phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">thrown</phrase> <phrase role="special">==</phrase> <phrase role="string">&quot;wfof_first&quot;</phrase><phrase role="special">);</phrase>
  12469. </programlisting>
  12470. </para>
  12471. </section>
  12472. <section id="fiber.when_any.when_any.when_any__produce_first_success">
  12473. <title><link linkend="fiber.when_any.when_any.when_any__produce_first_success">when_any,
  12474. produce first success</link></title>
  12475. <para>
  12476. One scenario for <quote>when_any</quote> functionality is when we're redundantly
  12477. contacting some number of possibly-unreliable web services. Not only might
  12478. they be slow &mdash; any one of them might produce a failure rather than the desired
  12479. result.
  12480. </para>
  12481. <para>
  12482. In such a case, <link linkend="wait_first_outcome"><code><phrase role="identifier">wait_first_outcome</phrase><phrase
  12483. role="special">()</phrase></code></link> isn't the right approach. If one
  12484. of the services produces an error quickly, while another follows up with
  12485. a real answer, we don't want to prefer the error just because it arrived
  12486. first!
  12487. </para>
  12488. <para>
  12489. Given the <code><phrase role="identifier">queue</phrase><phrase role="special">&lt;</phrase>
  12490. <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
  12491. <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
  12492. <phrase role="special">&gt;</phrase></code> we already constructed for
  12493. <code><phrase role="identifier">wait_first_outcome</phrase><phrase role="special">()</phrase></code>,
  12494. though, we can readily recast the interface function to deliver the first
  12495. <emphasis>successful</emphasis> result.
  12496. </para>
  12497. <para>
  12498. That does beg the question: what if <emphasis>all</emphasis> the task functions
  12499. throw an exception? In that case we'd probably better know about it.
  12500. </para>
  12501. <para>
  12502. <anchor id="exception_list"/>The <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4407.html#parallel.exceptions.synopsis">C++
  12503. Parallelism Draft Technical Specification</ulink> proposes a <code><phrase
  12504. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  12505. role="identifier">exception_list</phrase></code> exception capable of delivering
  12506. a collection of <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  12507. role="identifier">exception_ptr</phrase></code>s. Until that becomes universally
  12508. available, let's fake up an <code><phrase role="identifier">exception_list</phrase></code>
  12509. of our own:
  12510. </para>
  12511. <para>
  12512. <programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">exception_list</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase> <phrase role="special">{</phrase>
  12513. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  12514. <phrase role="identifier">exception_list</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">what</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
  12515. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">(</phrase> <phrase role="identifier">what</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12516. <phrase role="special">}</phrase>
  12517. <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">bundle_t</phrase><phrase role="special">;</phrase>
  12518. <phrase role="comment">// N4407 proposed std::exception_list API</phrase>
  12519. <phrase role="keyword">typedef</phrase> <phrase role="identifier">bundle_t</phrase><phrase role="special">::</phrase><phrase role="identifier">const_iterator</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">;</phrase>
  12520. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
  12521. <phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">();</phrase>
  12522. <phrase role="special">}</phrase>
  12523. <phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
  12524. <phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">begin</phrase><phrase role="special">();</phrase>
  12525. <phrase role="special">}</phrase>
  12526. <phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
  12527. <phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">end</phrase><phrase role="special">();</phrase>
  12528. <phrase role="special">}</phrase>
  12529. <phrase role="comment">// extension to populate</phrase>
  12530. <phrase role="keyword">void</phrase> <phrase role="identifier">add</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">ep</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12531. <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">push_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">ep</phrase><phrase role="special">);</phrase>
  12532. <phrase role="special">}</phrase>
  12533. <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
  12534. <phrase role="identifier">bundle_t</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">;</phrase>
  12535. <phrase role="special">};</phrase>
  12536. </programlisting>
  12537. </para>
  12538. <para>
  12539. Now we can build <code><phrase role="identifier">wait_first_success</phrase><phrase
  12540. role="special">()</phrase></code>, using <link linkend="wait_first_outcome_impl"><code><phrase
  12541. role="identifier">wait_first_outcome_impl</phrase><phrase role="special">()</phrase></code></link>.
  12542. </para>
  12543. <para>
  12544. Instead of retrieving only the first <code><phrase role="identifier">future</phrase><phrase
  12545. role="special">&lt;&gt;</phrase></code> from the queue, we must now loop
  12546. over <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
  12547. items. Of course we must limit that iteration! If we launch only <code><phrase
  12548. role="identifier">count</phrase></code> producer fibers, the <code><phrase
  12549. role="special">(</phrase><phrase role="identifier">count</phrase><phrase
  12550. role="special">+</phrase><phrase role="number">1</phrase><phrase role="special">)</phrase></code><superscript>st</superscript>
  12551. <link linkend="buffered_channel_pop"><code>buffered_channel::pop()</code></link> call
  12552. would block forever.
  12553. </para>
  12554. <para>
  12555. Given a ready <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>,
  12556. we can distinguish failure by calling <link linkend="future_get_exception_ptr"><code>future::get_exception_ptr()</code></link>.
  12557. If the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
  12558. in fact contains a result rather than an exception, <code><phrase role="identifier">get_exception_ptr</phrase><phrase
  12559. role="special">()</phrase></code> returns <code><phrase role="keyword">nullptr</phrase></code>.
  12560. In that case, we can confidently call <link linkend="future_get"><code>future::get()</code></link> to return
  12561. that result to our caller.
  12562. </para>
  12563. <para>
  12564. If the <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  12565. role="identifier">exception_ptr</phrase></code> is <emphasis>not</emphasis>
  12566. <code><phrase role="keyword">nullptr</phrase></code>, though, we collect
  12567. it into our pending <code><phrase role="identifier">exception_list</phrase></code>
  12568. and loop back for the next <code><phrase role="identifier">future</phrase><phrase
  12569. role="special">&lt;&gt;</phrase></code> from the queue.
  12570. </para>
  12571. <para>
  12572. If we fall out of the loop &mdash; if every single task fiber threw an exception
  12573. &mdash; we throw the <code><phrase role="identifier">exception_list</phrase></code>
  12574. exception into which we've been collecting those <code><phrase role="identifier">std</phrase><phrase
  12575. role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>s.
  12576. </para>
  12577. <para>
  12578. <anchor id="wait_first_success"/>
  12579. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  12580. <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase>
  12581. <phrase role="identifier">wait_first_success</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12582. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12583. <phrase role="comment">// In this case, the value we pass through the channel is actually a</phrase>
  12584. <phrase role="comment">// future -- which is already ready. future can carry either a value or an</phrase>
  12585. <phrase role="comment">// exception.</phrase>
  12586. <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
  12587. <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase>
  12588. <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
  12589. <phrase role="keyword">auto</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="number">64</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12590. <phrase role="comment">// launch all the relevant fibers</phrase>
  12591. <phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">,</phrase>
  12592. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
  12593. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
  12594. <phrase role="comment">// instantiate exception_list, just in case</phrase>
  12595. <phrase role="identifier">exception_list</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wait_first_success() produced only errors&quot;</phrase><phrase role="special">);</phrase>
  12596. <phrase role="comment">// retrieve up to 'count' results -- but stop there!</phrase>
  12597. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">count</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12598. <phrase role="comment">// retrieve the next future</phrase>
  12599. <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  12600. <phrase role="comment">// retrieve exception_ptr if any</phrase>
  12601. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">error</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get_exception_ptr</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  12602. <phrase role="comment">// if no error, then yay, return value</phrase>
  12603. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">error</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12604. <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
  12605. <phrase role="identifier">chanp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
  12606. <phrase role="comment">// show caller the value we got</phrase>
  12607. <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
  12608. <phrase role="special">}</phrase>
  12609. <phrase role="comment">// error is non-null: collect</phrase>
  12610. <phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">add</phrase><phrase role="special">(</phrase> <phrase role="identifier">error</phrase><phrase role="special">);</phrase>
  12611. <phrase role="special">}</phrase>
  12612. <phrase role="comment">// We only arrive here when every passed function threw an exception.</phrase>
  12613. <phrase role="comment">// Throw our collection to inform caller.</phrase>
  12614. <phrase role="keyword">throw</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">;</phrase>
  12615. <phrase role="special">}</phrase>
  12616. </programlisting>
  12617. </para>
  12618. <para>
  12619. A call might look like this:
  12620. </para>
  12621. <para>
  12622. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_success</phrase><phrase role="special">(</phrase>
  12623. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfss_first&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">,</phrase> <phrase role="keyword">true</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12624. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfss_second&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12625. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfss_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
  12626. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;wait_first_success(success) =&gt; &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">result</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  12627. <phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">result</phrase> <phrase role="special">==</phrase> <phrase role="string">&quot;wfss_second&quot;</phrase><phrase role="special">);</phrase>
  12628. </programlisting>
  12629. </para>
  12630. </section>
  12631. <section id="fiber.when_any.when_any.when_any__heterogeneous_types">
  12632. <title><link linkend="fiber.when_any.when_any.when_any__heterogeneous_types">when_any,
  12633. heterogeneous types</link></title>
  12634. <para>
  12635. We would be remiss to ignore the case in which the various task functions
  12636. have distinct return types. That means that the value returned by the first
  12637. of them might have any one of those types. We can express that with <ulink
  12638. url="http://www.boost.org/doc/libs/release/doc/html/variant.html">Boost.Variant</ulink>.
  12639. </para>
  12640. <para>
  12641. To keep the example simple, we'll revert to pretending that none of them
  12642. can throw an exception. That makes <code><phrase role="identifier">wait_first_value_het</phrase><phrase
  12643. role="special">()</phrase></code> strongly resemble <link linkend="wait_first_value"><code><phrase
  12644. role="identifier">wait_first_value</phrase><phrase role="special">()</phrase></code></link>.
  12645. We can actually reuse <link linkend="wait_first_value_impl"><code><phrase
  12646. role="identifier">wait_first_value_impl</phrase><phrase role="special">()</phrase></code></link>,
  12647. merely passing <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  12648. role="identifier">variant</phrase><phrase role="special">&lt;</phrase><phrase
  12649. role="identifier">T0</phrase><phrase role="special">,</phrase> <phrase
  12650. role="identifier">T1</phrase><phrase role="special">,</phrase> <phrase
  12651. role="special">...&gt;</phrase></code> as the queue's value type rather
  12652. than the common <code><phrase role="identifier">T</phrase></code>!
  12653. </para>
  12654. <para>
  12655. Naturally this could be extended to use <link linkend="wait_first_success"><code><phrase
  12656. role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link>
  12657. semantics instead.
  12658. </para>
  12659. <para>
  12660. <programlisting><phrase role="comment">// No need to break out the first Fn for interface function: let the compiler</phrase>
  12661. <phrase role="comment">// complain if empty.</phrase>
  12662. <phrase role="comment">// Our functions have different return types, and we might have to return any</phrase>
  12663. <phrase role="comment">// of them. Use a variant, expanding std::result_of&lt;Fn()&gt;::type for each Fn in</phrase>
  12664. <phrase role="comment">// parameter pack.</phrase>
  12665. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  12666. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variant</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">...</phrase> <phrase role="special">&gt;</phrase>
  12667. <phrase role="identifier">wait_first_value_het</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12668. <phrase role="comment">// Use buffered_channel&lt;boost::variant&lt;T1, T2, ...&gt;&gt;; see remarks above.</phrase>
  12669. <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variant</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">...</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
  12670. <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
  12671. <phrase role="keyword">auto</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="number">64</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12672. <phrase role="comment">// launch all the relevant fibers</phrase>
  12673. <phrase role="identifier">wait_first_value_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">,</phrase>
  12674. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
  12675. <phrase role="comment">// retrieve the first value</phrase>
  12676. <phrase role="identifier">return_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  12677. <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
  12678. <phrase role="identifier">chanp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
  12679. <phrase role="keyword">return</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
  12680. <phrase role="special">}</phrase>
  12681. </programlisting>
  12682. </para>
  12683. <para>
  12684. It might be called like this:
  12685. </para>
  12686. <para>
  12687. <programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variant</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase>
  12688. <phrase role="identifier">wait_first_value_het</phrase><phrase role="special">(</phrase>
  12689. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfvh_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12690. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="number">3.14</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12691. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="number">17</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
  12692. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;wait_first_value_het() =&gt; &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">result</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  12693. <phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase> <phrase role="special">==</phrase> <phrase role="number">17</phrase><phrase role="special">);</phrase>
  12694. </programlisting>
  12695. </para>
  12696. </section>
  12697. <section id="fiber.when_any.when_any.when_any__a_dubious_alternative">
  12698. <title><link linkend="fiber.when_any.when_any.when_any__a_dubious_alternative">when_any,
  12699. a dubious alternative</link></title>
  12700. <para>
  12701. Certain topics in C++ can arouse strong passions, and exceptions are no
  12702. exception. We cannot resist mentioning &mdash; for purely informational purposes
  12703. &mdash; that when you need only the <emphasis>first</emphasis> result from some
  12704. number of concurrently-running fibers, it would be possible to pass a
  12705. <literal>shared_ptr&lt;<link linkend="class_promise"><code>promise&lt;&gt;</code></link>&gt;</literal> to the
  12706. participating fibers, then cause the initiating fiber to call <link linkend="future_get"><code>future::get()</code></link> on
  12707. its <link linkend="class_future"><code>future&lt;&gt;</code></link>. The first fiber to call <link linkend="promise_set_value"><code>promise::set_value()</code></link> on
  12708. that shared <code><phrase role="identifier">promise</phrase></code> will
  12709. succeed; subsequent <code><phrase role="identifier">set_value</phrase><phrase
  12710. role="special">()</phrase></code> calls on the same <code><phrase role="identifier">promise</phrase></code>
  12711. instance will throw <code><phrase role="identifier">future_error</phrase></code>.
  12712. </para>
  12713. <para>
  12714. Use this information at your own discretion. Beware the dark side.
  12715. </para>
  12716. </section>
  12717. </section>
  12718. <section id="fiber.when_any.when_all_functionality">
  12719. <title><link linkend="fiber.when_any.when_all_functionality">when_all functionality</link></title>
  12720. <section id="fiber.when_any.when_all_functionality.when_all__simple_completion">
  12721. <title><link linkend="fiber.when_any.when_all_functionality.when_all__simple_completion">when_all,
  12722. simple completion</link></title>
  12723. <para>
  12724. For the case in which we must wait for <emphasis>all</emphasis> task functions
  12725. to complete &mdash; but we don't need results (or expect exceptions) from any of
  12726. them &mdash; we can write <code><phrase role="identifier">wait_all_simple</phrase><phrase
  12727. role="special">()</phrase></code> that looks remarkably like <link linkend="wait_first_simple"><code><phrase
  12728. role="identifier">wait_first_simple</phrase><phrase role="special">()</phrase></code></link>.
  12729. The difference is that instead of our <link linkend="wait_done"><code><phrase
  12730. role="identifier">Done</phrase></code></link> class, we instantiate a <link linkend="class_barrier"><code>barrier</code></link> and
  12731. call its <link linkend="barrier_wait"><code>barrier::wait()</code></link>.
  12732. </para>
  12733. <para>
  12734. We initialize the <code><phrase role="identifier">barrier</phrase></code>
  12735. with <code><phrase role="special">(</phrase><phrase role="identifier">count</phrase><phrase
  12736. role="special">+</phrase><phrase role="number">1</phrase><phrase role="special">)</phrase></code>
  12737. because we are launching <code><phrase role="identifier">count</phrase></code>
  12738. fibers, plus the <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code>
  12739. call within <code><phrase role="identifier">wait_all_simple</phrase><phrase
  12740. role="special">()</phrase></code> itself.
  12741. </para>
  12742. <para>
  12743. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  12744. <phrase role="keyword">void</phrase> <phrase role="identifier">wait_all_simple</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12745. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12746. <phrase role="comment">// Initialize a barrier(count+1) because we'll immediately wait on it. We</phrase>
  12747. <phrase role="comment">// don't want to wake up until 'count' more fibers wait on it. Even though</phrase>
  12748. <phrase role="comment">// we'll stick around until the last of them completes, use shared_ptr</phrase>
  12749. <phrase role="comment">// anyway because it's easier to be confident about lifespan issues.</phrase>
  12750. <phrase role="keyword">auto</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">barrier</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">count</phrase> <phrase role="special">+</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12751. <phrase role="identifier">wait_all_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
  12752. <phrase role="identifier">barrier</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
  12753. <phrase role="special">}</phrase>
  12754. </programlisting>
  12755. </para>
  12756. <para>
  12757. As stated above, the only difference between <code><phrase role="identifier">wait_all_simple_impl</phrase><phrase
  12758. role="special">()</phrase></code> and <link linkend="wait_first_simple_impl"><code><phrase
  12759. role="identifier">wait_first_simple_impl</phrase><phrase role="special">()</phrase></code></link>
  12760. is that the former calls <code><phrase role="identifier">barrier</phrase><phrase
  12761. role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
  12762. role="special">()</phrase></code> rather than <code><phrase role="identifier">Done</phrase><phrase
  12763. role="special">::</phrase><phrase role="identifier">notify</phrase><phrase
  12764. role="special">()</phrase></code>:
  12765. </para>
  12766. <para>
  12767. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  12768. <phrase role="keyword">void</phrase> <phrase role="identifier">wait_all_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">barrier</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase>
  12769. <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12770. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase>
  12771. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
  12772. <phrase role="special">[](</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">barrier</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase>
  12773. <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase>
  12774. <phrase role="identifier">function</phrase><phrase role="special">();</phrase>
  12775. <phrase role="identifier">barrier</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
  12776. <phrase role="special">},</phrase>
  12777. <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase>
  12778. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase>
  12779. <phrase role="special">)).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
  12780. <phrase role="identifier">wait_all_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
  12781. <phrase role="special">}</phrase>
  12782. </programlisting>
  12783. </para>
  12784. <para>
  12785. You might call it like this:
  12786. </para>
  12787. <para>
  12788. <programlisting><phrase role="identifier">wait_all_simple</phrase><phrase role="special">(</phrase>
  12789. <phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;was_long&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12790. <phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;was_medium&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12791. <phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;was_short&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
  12792. </programlisting>
  12793. </para>
  12794. <para>
  12795. Control will not return from the <code><phrase role="identifier">wait_all_simple</phrase><phrase
  12796. role="special">()</phrase></code> call until the last of its task functions
  12797. has completed.
  12798. </para>
  12799. </section>
  12800. <section id="fiber.when_any.when_all_functionality.when_all__return_values">
  12801. <title><link linkend="fiber.when_any.when_all_functionality.when_all__return_values">when_all,
  12802. return values</link></title>
  12803. <para>
  12804. As soon as we want to collect return values from all the task functions,
  12805. we can see right away how to reuse <link linkend="wait_first_value"><code><phrase
  12806. role="identifier">wait_first_value</phrase><phrase role="special">()</phrase></code></link>'s
  12807. queue&lt;T&gt; for the purpose. All we have to do is avoid closing it after
  12808. the first value!
  12809. </para>
  12810. <para>
  12811. But in fact, collecting multiple values raises an interesting question:
  12812. do we <emphasis>really</emphasis> want to wait until the slowest of them
  12813. has arrived? Wouldn't we rather process each result as soon as it becomes
  12814. available?
  12815. </para>
  12816. <para>
  12817. Fortunately we can present both APIs. Let's define <code><phrase role="identifier">wait_all_values_source</phrase><phrase
  12818. role="special">()</phrase></code> to return <code><phrase role="identifier">shared_ptr</phrase><phrase
  12819. role="special">&lt;</phrase><phrase role="identifier">buffered_channel</phrase><phrase
  12820. role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
  12821. role="special">&gt;&gt;</phrase></code>.
  12822. </para>
  12823. <para>
  12824. <anchor id="wait_all_values"/>Given <code><phrase role="identifier">wait_all_values_source</phrase><phrase
  12825. role="special">()</phrase></code>, it's straightforward to implement <code><phrase
  12826. role="identifier">wait_all_values</phrase><phrase role="special">()</phrase></code>:
  12827. </para>
  12828. <para>
  12829. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  12830. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase>
  12831. <phrase role="identifier">wait_all_values</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12832. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12833. <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
  12834. <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">vector_t</phrase><phrase role="special">;</phrase>
  12835. <phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
  12836. <phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">reserve</phrase><phrase role="special">(</phrase> <phrase role="identifier">count</phrase><phrase role="special">);</phrase>
  12837. <phrase role="comment">// get channel</phrase>
  12838. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">chan</phrase> <phrase role="special">=</phrase>
  12839. <phrase role="identifier">wait_all_values_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
  12840. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
  12841. <phrase role="comment">// fill results vector</phrase>
  12842. <phrase role="identifier">return_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
  12843. <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">value</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12844. <phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">push_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
  12845. <phrase role="special">}</phrase>
  12846. <phrase role="comment">// return vector to caller</phrase>
  12847. <phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
  12848. <phrase role="special">}</phrase>
  12849. </programlisting>
  12850. </para>
  12851. <para>
  12852. It might be called like this:
  12853. </para>
  12854. <para>
  12855. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">values</phrase> <phrase role="special">=</phrase>
  12856. <phrase role="identifier">wait_all_values</phrase><phrase role="special">(</phrase>
  12857. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wav_late&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12858. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wav_middle&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12859. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wav_early&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
  12860. </programlisting>
  12861. </para>
  12862. <para>
  12863. As you can see from the loop in <code><phrase role="identifier">wait_all_values</phrase><phrase
  12864. role="special">()</phrase></code>, instead of requiring its caller to count
  12865. values, we define <code><phrase role="identifier">wait_all_values_source</phrase><phrase
  12866. role="special">()</phrase></code> to <link linkend="buffered_channel_close"><code>buffered_channel::close()</code></link> the
  12867. queue when done. But how do we do that? Each producer fiber is independent.
  12868. It has no idea whether it is the last one to <link linkend="buffered_channel_push"><code>buffered_channel::push()</code></link> a
  12869. value.
  12870. </para>
  12871. <para>
  12872. <anchor id="wait_nqueue"/>We can address that problem with a counting façade
  12873. for the <code><phrase role="identifier">queue</phrase><phrase role="special">&lt;&gt;</phrase></code>.
  12874. In fact, our façade need only support the producer end of the queue.
  12875. </para>
  12876. <para>
  12877. [wait_nqueue]
  12878. </para>
  12879. <para>
  12880. <anchor id="wait_all_values_source"/>Armed with <code><phrase role="identifier">nqueue</phrase><phrase
  12881. role="special">&lt;&gt;</phrase></code>, we can implement <code><phrase
  12882. role="identifier">wait_all_values_source</phrase><phrase role="special">()</phrase></code>.
  12883. It starts just like <link linkend="wait_first_value"><code><phrase role="identifier">wait_first_value</phrase><phrase
  12884. role="special">()</phrase></code></link>. The difference is that we wrap
  12885. the <code><phrase role="identifier">queue</phrase><phrase role="special">&lt;</phrase><phrase
  12886. role="identifier">T</phrase><phrase role="special">&gt;</phrase></code>
  12887. with an <code><phrase role="identifier">nqueue</phrase><phrase role="special">&lt;</phrase><phrase
  12888. role="identifier">T</phrase><phrase role="special">&gt;</phrase></code>
  12889. to pass to the producer fibers.
  12890. </para>
  12891. <para>
  12892. Then, of course, instead of popping the first value, closing the queue
  12893. and returning it, we simply return the <code><phrase role="identifier">shared_ptr</phrase><phrase
  12894. role="special">&lt;</phrase><phrase role="identifier">queue</phrase><phrase
  12895. role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
  12896. role="special">&gt;&gt;</phrase></code>.
  12897. </para>
  12898. <para>
  12899. <programlisting><phrase role="comment">// Return a shared_ptr&lt;buffered_channel&lt;T&gt;&gt; from which the caller can</phrase>
  12900. <phrase role="comment">// retrieve each new result as it arrives, until 'closed'.</phrase>
  12901. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  12902. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
  12903. <phrase role="identifier">wait_all_values_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12904. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12905. <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
  12906. <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
  12907. <phrase role="comment">// make the channel</phrase>
  12908. <phrase role="keyword">auto</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="number">64</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12909. <phrase role="comment">// and make an nchannel facade to close it after 'count' items</phrase>
  12910. <phrase role="keyword">auto</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">nchannel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">,</phrase> <phrase role="identifier">count</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12911. <phrase role="comment">// pass that nchannel facade to all the relevant fibers</phrase>
  12912. <phrase role="identifier">wait_all_values_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">,</phrase>
  12913. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
  12914. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
  12915. <phrase role="comment">// then return the channel for consumer</phrase>
  12916. <phrase role="keyword">return</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">;</phrase>
  12917. <phrase role="special">}</phrase>
  12918. </programlisting>
  12919. </para>
  12920. <para>
  12921. For example:
  12922. </para>
  12923. <para>
  12924. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">chan</phrase> <phrase role="special">=</phrase>
  12925. <phrase role="identifier">wait_all_values_source</phrase><phrase role="special">(</phrase>
  12926. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wavs_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12927. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wavs_second&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  12928. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wavs_first&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
  12929. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
  12930. <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">value</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12931. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;wait_all_values_source() =&gt; '&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">value</phrase>
  12932. <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;'&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  12933. <phrase role="special">}</phrase>
  12934. </programlisting>
  12935. </para>
  12936. <para>
  12937. <anchor id="wait_all_values_impl"/><code><phrase role="identifier">wait_all_values_impl</phrase><phrase
  12938. role="special">()</phrase></code> really is just like <link linkend="wait_first_value_impl"><code><phrase
  12939. role="identifier">wait_first_value_impl</phrase><phrase role="special">()</phrase></code></link>
  12940. except for the use of <code><phrase role="identifier">nqueue</phrase><phrase
  12941. role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
  12942. role="special">&gt;</phrase></code> rather than <code><phrase role="identifier">queue</phrase><phrase
  12943. role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
  12944. role="special">&gt;</phrase></code>:
  12945. </para>
  12946. <para>
  12947. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;</phrase>
  12948. <phrase role="keyword">void</phrase> <phrase role="identifier">wait_all_values_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">nchannel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">,</phrase>
  12949. <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12950. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">chan</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase>
  12951. <phrase role="identifier">chan</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase><phrase role="identifier">function</phrase><phrase role="special">());</phrase>
  12952. <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
  12953. <phrase role="special">}</phrase>
  12954. </programlisting>
  12955. </para>
  12956. </section>
  12957. <section id="fiber.when_any.when_all_functionality.when_all_until_first_exception">
  12958. <title><link linkend="fiber.when_any.when_all_functionality.when_all_until_first_exception">when_all
  12959. until first exception</link></title>
  12960. <para>
  12961. Naturally, just as with <link linkend="wait_first_outcome"><code><phrase
  12962. role="identifier">wait_first_outcome</phrase><phrase role="special">()</phrase></code></link>,
  12963. we can elaborate <link linkend="wait_all_values"><code><phrase role="identifier">wait_all_values</phrase><phrase
  12964. role="special">()</phrase></code></link> and <link linkend="wait_all_values_source"><code><phrase
  12965. role="identifier">wait_all_values_source</phrase><phrase role="special">()</phrase></code></link>
  12966. by passing <code><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
  12967. <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code>
  12968. instead of plain <code><phrase role="identifier">T</phrase></code>.
  12969. </para>
  12970. <para>
  12971. <anchor id="wait_all_until_error"/><code><phrase role="identifier">wait_all_until_error</phrase><phrase
  12972. role="special">()</phrase></code> pops that <code><phrase role="identifier">future</phrase><phrase
  12973. role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase
  12974. role="special">&gt;</phrase></code> and calls its <link linkend="future_get"><code>future::get()</code></link>:
  12975. </para>
  12976. <para>
  12977. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  12978. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase>
  12979. <phrase role="identifier">wait_all_until_error</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12980. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12981. <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
  12982. <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase>
  12983. <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">vector_t</phrase><phrase role="special">;</phrase>
  12984. <phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
  12985. <phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">reserve</phrase><phrase role="special">(</phrase> <phrase role="identifier">count</phrase><phrase role="special">);</phrase>
  12986. <phrase role="comment">// get channel</phrase>
  12987. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
  12988. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">(</phrase>
  12989. <phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
  12990. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
  12991. <phrase role="comment">// fill results vector</phrase>
  12992. <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase>
  12993. <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  12994. <phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">push_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  12995. <phrase role="special">}</phrase>
  12996. <phrase role="comment">// return vector to caller</phrase>
  12997. <phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
  12998. <phrase role="special">}</phrase>
  12999. </programlisting>
  13000. </para>
  13001. <para>
  13002. For example:
  13003. </para>
  13004. <para>
  13005. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">thrown</phrase><phrase role="special">;</phrase>
  13006. <phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
  13007. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">values</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_all_until_error</phrase><phrase role="special">(</phrase>
  13008. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;waue_late&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  13009. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;waue_middle&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">,</phrase> <phrase role="keyword">true</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  13010. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;waue_early&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
  13011. <phrase role="special">}</phrase> <phrase role="keyword">catch</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">e</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13012. <phrase role="identifier">thrown</phrase> <phrase role="special">=</phrase> <phrase role="identifier">e</phrase><phrase role="special">.</phrase><phrase role="identifier">what</phrase><phrase role="special">();</phrase>
  13013. <phrase role="special">}</phrase>
  13014. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;wait_all_until_error(fail) threw '&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">thrown</phrase>
  13015. <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;'&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  13016. </programlisting>
  13017. </para>
  13018. <para>
  13019. <anchor id="wait_all_until_error_source"/>Naturally this complicates the
  13020. API for <code><phrase role="identifier">wait_all_until_error_source</phrase><phrase
  13021. role="special">()</phrase></code>. The caller must both retrieve a <code><phrase
  13022. role="identifier">future</phrase><phrase role="special">&lt;</phrase>
  13023. <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code>
  13024. and call its <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
  13025. method. It would, of course, be possible to return a façade over the consumer
  13026. end of the queue that would implicitly perform the <code><phrase role="identifier">get</phrase><phrase
  13027. role="special">()</phrase></code> and return a simple <code><phrase role="identifier">T</phrase></code>
  13028. (or throw).
  13029. </para>
  13030. <para>
  13031. The implementation is just as you would expect. Notice, however, that we
  13032. can reuse <link linkend="wait_first_outcome_impl"><code><phrase role="identifier">wait_first_outcome_impl</phrase><phrase
  13033. role="special">()</phrase></code></link>, passing the <code><phrase role="identifier">nqueue</phrase><phrase
  13034. role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
  13035. role="special">&gt;</phrase></code> rather than <code><phrase role="identifier">queue</phrase><phrase
  13036. role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
  13037. role="special">&gt;</phrase></code>.
  13038. </para>
  13039. <para>
  13040. <programlisting><phrase role="comment">// Return a shared_ptr&lt;buffered_channel&lt;future&lt;T&gt;&gt;&gt; from which the caller can</phrase>
  13041. <phrase role="comment">// get() each new result as it arrives, until 'closed'.</phrase>
  13042. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  13043. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
  13044. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase>
  13045. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
  13046. <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
  13047. <phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13048. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  13049. <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
  13050. <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase>
  13051. <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
  13052. <phrase role="comment">// make the channel</phrase>
  13053. <phrase role="keyword">auto</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="number">64</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  13054. <phrase role="comment">// and make an nchannel facade to close it after 'count' items</phrase>
  13055. <phrase role="keyword">auto</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">nchannel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">,</phrase> <phrase role="identifier">count</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  13056. <phrase role="comment">// pass that nchannel facade to all the relevant fibers</phrase>
  13057. <phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">,</phrase>
  13058. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
  13059. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
  13060. <phrase role="comment">// then return the channel for consumer</phrase>
  13061. <phrase role="keyword">return</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">;</phrase>
  13062. <phrase role="special">}</phrase>
  13063. </programlisting>
  13064. </para>
  13065. <para>
  13066. For example:
  13067. </para>
  13068. <para>
  13069. <programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase>
  13070. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">chan</phrase> <phrase role="special">=</phrase>
  13071. <phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase>
  13072. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wauess_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  13073. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wauess_second&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  13074. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wauess_first&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
  13075. <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase>
  13076. <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13077. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">value</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  13078. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;wait_all_until_error_source(success) =&gt; '&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">value</phrase>
  13079. <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;'&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  13080. <phrase role="special">}</phrase>
  13081. </programlisting>
  13082. </para>
  13083. </section>
  13084. <section id="fiber.when_any.when_all_functionality.wait_all__collecting_all_exceptions">
  13085. <title><link linkend="fiber.when_any.when_all_functionality.wait_all__collecting_all_exceptions">wait_all,
  13086. collecting all exceptions</link></title>
  13087. <para>
  13088. <anchor id="wait_all_collect_errors"/>Given <link linkend="wait_all_until_error_source"><code><phrase
  13089. role="identifier">wait_all_until_error_source</phrase><phrase role="special">()</phrase></code></link>,
  13090. it might be more reasonable to make a <code><phrase role="identifier">wait_all_</phrase><phrase
  13091. role="special">...()</phrase></code> that collects <emphasis>all</emphasis>
  13092. errors instead of presenting only the first:
  13093. </para>
  13094. <para>
  13095. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  13096. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase>
  13097. <phrase role="identifier">wait_all_collect_errors</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13098. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  13099. <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
  13100. <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase>
  13101. <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">vector_t</phrase><phrase role="special">;</phrase>
  13102. <phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
  13103. <phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">reserve</phrase><phrase role="special">(</phrase> <phrase role="identifier">count</phrase><phrase role="special">);</phrase>
  13104. <phrase role="identifier">exception_list</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wait_all_collect_errors() exceptions&quot;</phrase><phrase role="special">);</phrase>
  13105. <phrase role="comment">// get channel</phrase>
  13106. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
  13107. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">(</phrase>
  13108. <phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
  13109. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
  13110. <phrase role="comment">// fill results and/or exceptions vectors</phrase>
  13111. <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase>
  13112. <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13113. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">exp</phrase> <phrase role="special">=</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase>
  13114. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">exp</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13115. <phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">push_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  13116. <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
  13117. <phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">add</phrase><phrase role="special">(</phrase> <phrase role="identifier">exp</phrase><phrase role="special">);</phrase>
  13118. <phrase role="special">}</phrase>
  13119. <phrase role="special">}</phrase>
  13120. <phrase role="comment">// if there were any exceptions, throw</phrase>
  13121. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13122. <phrase role="keyword">throw</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">;</phrase>
  13123. <phrase role="special">}</phrase>
  13124. <phrase role="comment">// no exceptions: return vector to caller</phrase>
  13125. <phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
  13126. <phrase role="special">}</phrase>
  13127. </programlisting>
  13128. </para>
  13129. <para>
  13130. The implementation is a simple variation on <link linkend="wait_first_success"><code><phrase
  13131. role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link>,
  13132. using the same <link linkend="exception_list"><code><phrase role="identifier">exception_list</phrase></code></link>
  13133. exception class.
  13134. </para>
  13135. </section>
  13136. <section id="fiber.when_any.when_all_functionality.when_all__heterogeneous_types">
  13137. <title><link linkend="fiber.when_any.when_all_functionality.when_all__heterogeneous_types">when_all,
  13138. heterogeneous types</link></title>
  13139. <para>
  13140. But what about the case when we must wait for all results of different
  13141. types?
  13142. </para>
  13143. <para>
  13144. We can present an API that is frankly quite cool. Consider a sample struct:
  13145. </para>
  13146. <para>
  13147. <programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">Data</phrase> <phrase role="special">{</phrase>
  13148. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">str</phrase><phrase role="special">;</phrase>
  13149. <phrase role="keyword">double</phrase> <phrase role="identifier">inexact</phrase><phrase role="special">;</phrase>
  13150. <phrase role="keyword">int</phrase> <phrase role="identifier">exact</phrase><phrase role="special">;</phrase>
  13151. <phrase role="keyword">friend</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostream</phrase><phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;&lt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostream</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="identifier">Data</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase>
  13152. <phrase role="special">...</phrase>
  13153. <phrase role="special">};</phrase>
  13154. </programlisting>
  13155. </para>
  13156. <para>
  13157. Let's fill its members from task functions all running concurrently:
  13158. </para>
  13159. <para>
  13160. <programlisting><phrase role="identifier">Data</phrase> <phrase role="identifier">data</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_all_members</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Data</phrase> <phrase role="special">&gt;(</phrase>
  13161. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wams_left&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  13162. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="number">3.14</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  13163. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="number">17</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
  13164. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;wait_all_members&lt;Data&gt;(success) =&gt; &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">data</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  13165. </programlisting>
  13166. </para>
  13167. <para>
  13168. Note that for this case, we abandon the notion of capturing the earliest
  13169. result first, and so on: we must fill exactly the passed struct in left-to-right
  13170. order.
  13171. </para>
  13172. <para>
  13173. That permits a beautifully simple implementation:
  13174. </para>
  13175. <para>
  13176. <programlisting><phrase role="comment">// Explicitly pass Result. This can be any type capable of being initialized</phrase>
  13177. <phrase role="comment">// from the results of the passed functions, such as a struct.</phrase>
  13178. <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Result</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
  13179. <phrase role="identifier">Result</phrase> <phrase role="identifier">wait_all_members</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13180. <phrase role="comment">// Run each of the passed functions on a separate fiber, passing all their</phrase>
  13181. <phrase role="comment">// futures to helper function for processing.</phrase>
  13182. <phrase role="keyword">return</phrase> <phrase role="identifier">wait_all_members_get</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Result</phrase> <phrase role="special">&gt;(</phrase>
  13183. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">async</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
  13184. <phrase role="special">}</phrase>
  13185. </programlisting>
  13186. </para>
  13187. <para>
  13188. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Result</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Futures</phrase> <phrase role="special">&gt;</phrase>
  13189. <phrase role="identifier">Result</phrase> <phrase role="identifier">wait_all_members_get</phrase><phrase role="special">(</phrase> <phrase role="identifier">Futures</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">futures</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13190. <phrase role="comment">// Fetch the results from the passed futures into Result's initializer</phrase>
  13191. <phrase role="comment">// list. It's true that the get() calls here will block the implicit</phrase>
  13192. <phrase role="comment">// iteration over futures -- but that doesn't matter because we won't be</phrase>
  13193. <phrase role="comment">// done until the slowest of them finishes anyway. As results are</phrase>
  13194. <phrase role="comment">// processed in argument-list order rather than order of completion, the</phrase>
  13195. <phrase role="comment">// leftmost get() to throw an exception will cause that exception to</phrase>
  13196. <phrase role="comment">// propagate to the caller.</phrase>
  13197. <phrase role="keyword">return</phrase> <phrase role="identifier">Result</phrase><phrase role="special">{</phrase> <phrase role="identifier">futures</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">...</phrase> <phrase role="special">};</phrase>
  13198. <phrase role="special">}</phrase>
  13199. </programlisting>
  13200. </para>
  13201. <para>
  13202. It is tempting to try to implement <code><phrase role="identifier">wait_all_members</phrase><phrase
  13203. role="special">()</phrase></code> as a one-liner like this:
  13204. </para>
  13205. <programlisting><phrase role="keyword">return</phrase> <phrase role="identifier">Result</phrase><phrase role="special">{</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">async</phrase><phrase role="special">(</phrase><phrase role="identifier">functions</phrase><phrase role="special">).</phrase><phrase role="identifier">get</phrase><phrase role="special">()...</phrase> <phrase role="special">};</phrase>
  13206. </programlisting>
  13207. <para>
  13208. The trouble with this tactic is that it would serialize all the task functions.
  13209. The runtime makes a single pass through <code><phrase role="identifier">functions</phrase></code>,
  13210. calling <link linkend="fibers_async"><code>fibers::async()</code></link> for each and then immediately calling
  13211. <link linkend="future_get"><code>future::get()</code></link> on its returned <code><phrase role="identifier">future</phrase><phrase
  13212. role="special">&lt;&gt;</phrase></code>. That blocks the implicit loop.
  13213. The above is almost equivalent to writing:
  13214. </para>
  13215. <programlisting><phrase role="keyword">return</phrase> <phrase role="identifier">Result</phrase><phrase role="special">{</phrase> <phrase role="identifier">functions</phrase><phrase role="special">()...</phrase> <phrase role="special">};</phrase>
  13216. </programlisting>
  13217. <para>
  13218. in which, of course, there is no concurrency at all.
  13219. </para>
  13220. <para>
  13221. Passing the argument pack through a function-call boundary (<code><phrase
  13222. role="identifier">wait_all_members_get</phrase><phrase role="special">()</phrase></code>)
  13223. forces the runtime to make <emphasis>two</emphasis> passes: one in <code><phrase
  13224. role="identifier">wait_all_members</phrase><phrase role="special">()</phrase></code>
  13225. to collect the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>s
  13226. from all the <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code>
  13227. calls, the second in <code><phrase role="identifier">wait_all_members_get</phrase><phrase
  13228. role="special">()</phrase></code> to fetch each of the results.
  13229. </para>
  13230. <para>
  13231. As noted in comments, within the <code><phrase role="identifier">wait_all_members_get</phrase><phrase
  13232. role="special">()</phrase></code> parameter pack expansion pass, the blocking
  13233. behavior of <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
  13234. becomes irrelevant. Along the way, we will hit the <code><phrase role="identifier">get</phrase><phrase
  13235. role="special">()</phrase></code> for the slowest task function; after
  13236. that every subsequent <code><phrase role="identifier">get</phrase><phrase
  13237. role="special">()</phrase></code> will complete in trivial time.
  13238. </para>
  13239. <para>
  13240. By the way, we could also use this same API to fill a vector or other collection:
  13241. </para>
  13242. <para>
  13243. <programlisting><phrase role="comment">// If we don't care about obtaining results as soon as they arrive, and we</phrase>
  13244. <phrase role="comment">// prefer a result vector in passed argument order rather than completion</phrase>
  13245. <phrase role="comment">// order, wait_all_members() is another possible implementation of</phrase>
  13246. <phrase role="comment">// wait_all_until_error().</phrase>
  13247. <phrase role="keyword">auto</phrase> <phrase role="identifier">strings</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_all_members</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;(</phrase>
  13248. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wamv_left&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  13249. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wamv_middle&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
  13250. <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wamv_right&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
  13251. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;wait_all_members&lt;vector&gt;() =&gt;&quot;</phrase><phrase role="special">;</phrase>
  13252. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">str</phrase> <phrase role="special">:</phrase> <phrase role="identifier">strings</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13253. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; '&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">str</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;'&quot;</phrase><phrase role="special">;</phrase>
  13254. <phrase role="special">}</phrase>
  13255. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  13256. </programlisting>
  13257. </para>
  13258. </section>
  13259. </section>
  13260. </section>
  13261. <section id="fiber.integration">
  13262. <title><anchor id="integration"/><link linkend="fiber.integration">Sharing a
  13263. Thread with Another Main Loop</link></title>
  13264. <section id="fiber.integration.overview">
  13265. <title><link linkend="fiber.integration.overview">Overview</link></title>
  13266. <para>
  13267. As always with cooperative concurrency, it is important not to let any one
  13268. fiber monopolize the processor too long: that could <quote>starve</quote>
  13269. other ready fibers. This section discusses a couple of solutions.
  13270. </para>
  13271. </section>
  13272. <section id="fiber.integration.event_driven_program">
  13273. <title><link linkend="fiber.integration.event_driven_program">Event-Driven
  13274. Program</link></title>
  13275. <para>
  13276. Consider a classic event-driven program, organized around a main loop that
  13277. fetches and dispatches incoming I/O events. You are introducing <emphasis
  13278. role="bold">Boost.Fiber</emphasis> because certain asynchronous I/O sequences
  13279. are logically sequential, and for those you want to write and maintain code
  13280. that looks and acts sequential.
  13281. </para>
  13282. <para>
  13283. You are launching fibers on the application&#8217;s main thread because certain
  13284. of their actions will affect its user interface, and the application&#8217;s UI
  13285. framework permits UI operations only on the main thread. Or perhaps those
  13286. fibers need access to main-thread data, and it would be too expensive in
  13287. runtime (or development time) to robustly defend every such data item with
  13288. thread synchronization primitives.
  13289. </para>
  13290. <para>
  13291. You must ensure that the application&#8217;s main loop <emphasis>itself</emphasis>
  13292. doesn&#8217;t monopolize the processor: that the fibers it launches will get the
  13293. CPU cycles they need.
  13294. </para>
  13295. <para>
  13296. The solution is the same as for any fiber that might claim the CPU for an
  13297. extended time: introduce calls to <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>. The
  13298. most straightforward approach is to call <code><phrase role="identifier">yield</phrase><phrase
  13299. role="special">()</phrase></code> on every iteration of your existing main
  13300. loop. In effect, this unifies the application&#8217;s main loop with <emphasis role="bold">Boost.Fiber</emphasis>&#8217;s
  13301. internal main loop. <code><phrase role="identifier">yield</phrase><phrase
  13302. role="special">()</phrase></code> allows the fiber manager to run any fibers
  13303. that have become ready since the previous iteration of the application&#8217;s main
  13304. loop. When these fibers have had a turn, control passes to the thread&#8217;s main
  13305. fiber, which returns from <code><phrase role="identifier">yield</phrase><phrase
  13306. role="special">()</phrase></code> and resumes the application&#8217;s main loop.
  13307. </para>
  13308. </section>
  13309. <section id="fiber.integration.embedded_main_loop">
  13310. <title><anchor id="embedded_main_loop"/><link linkend="fiber.integration.embedded_main_loop">Embedded
  13311. Main Loop</link></title>
  13312. <para>
  13313. More challenging is when the application&#8217;s main loop is embedded in some other
  13314. library or framework. Such an application will typically, after performing
  13315. all necessary setup, pass control to some form of <code><phrase role="identifier">run</phrase><phrase
  13316. role="special">()</phrase></code> function from which control does not return
  13317. until application shutdown.
  13318. </para>
  13319. <para>
  13320. A <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
  13321. program might call <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html"><code><phrase
  13322. role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
  13323. role="identifier">run</phrase><phrase role="special">()</phrase></code></ulink>
  13324. in this way.
  13325. </para>
  13326. <para>
  13327. In general, the trick is to arrange to pass control to <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link> frequently.
  13328. You could use an <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/high_resolution_timer.html">Asio
  13329. timer</ulink> for that purpose. You could instantiate the timer, arranging
  13330. to call a handler function when the timer expires. The handler function could
  13331. call <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>,
  13332. then reset the timer and arrange to wake up again on its next expiration.
  13333. </para>
  13334. <para>
  13335. Since, in this thought experiment, we always pass control to the fiber manager
  13336. via <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>,
  13337. the calling fiber is never blocked. Therefore there is always at least one
  13338. ready fiber. Therefore the fiber manager never calls <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>.
  13339. </para>
  13340. <para>
  13341. Using <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/post.html"><code><phrase
  13342. role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
  13343. role="identifier">post</phrase><phrase role="special">()</phrase></code></ulink>
  13344. instead of setting a timer for some nonzero interval would be unfriendly
  13345. to other threads. When all I/O is pending and all fibers are blocked, the
  13346. io_service and the fiber manager would simply spin the CPU, passing control
  13347. back and forth to each other. Using a timer allows tuning the responsiveness
  13348. of this thread relative to others.
  13349. </para>
  13350. </section>
  13351. <section id="fiber.integration.deeper_dive_into___boost_asio__">
  13352. <title><link linkend="fiber.integration.deeper_dive_into___boost_asio__">Deeper
  13353. Dive into <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link></title>
  13354. <para>
  13355. By now the alert reader is thinking: but surely, with Asio in particular,
  13356. we ought to be able to do much better than periodic polling pings!
  13357. </para>
  13358. <para>
  13359. This turns out to be surprisingly tricky. We present a possible approach
  13360. in <ulink url="../../examples/asio/round_robin.hpp"><code><phrase role="identifier">examples</phrase><phrase
  13361. role="special">/</phrase><phrase role="identifier">asio</phrase><phrase role="special">/</phrase><phrase
  13362. role="identifier">round_robin</phrase><phrase role="special">.</phrase><phrase
  13363. role="identifier">hpp</phrase></code></ulink>.
  13364. </para>
  13365. <para>
  13366. One consequence of using <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
  13367. is that you must always let Asio suspend the running thread. Since Asio is
  13368. aware of pending I/O requests, it can arrange to suspend the thread in such
  13369. a way that the OS will wake it on I/O completion. No one else has sufficient
  13370. knowledge.
  13371. </para>
  13372. <para>
  13373. So the fiber scheduler must depend on Asio for suspension and resumption.
  13374. It requires Asio handler calls to wake it.
  13375. </para>
  13376. <para>
  13377. One dismaying implication is that we cannot support multiple threads calling
  13378. <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html"><code><phrase
  13379. role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
  13380. role="identifier">run</phrase><phrase role="special">()</phrase></code></ulink>
  13381. on the same <code><phrase role="identifier">io_service</phrase></code> instance.
  13382. The reason is that Asio provides no way to constrain a particular handler
  13383. to be called only on a specified thread. A fiber scheduler instance is locked
  13384. to a particular thread: that instance cannot manage any other thread&#8217;s fibers.
  13385. Yet if we allow multiple threads to call <code><phrase role="identifier">io_service</phrase><phrase
  13386. role="special">::</phrase><phrase role="identifier">run</phrase><phrase role="special">()</phrase></code>
  13387. on the same <code><phrase role="identifier">io_service</phrase></code> instance,
  13388. a fiber scheduler which needs to sleep can have no guarantee that it will
  13389. reawaken in a timely manner. It can set an Asio timer, as described above
  13390. &mdash; but that timer&#8217;s handler may well execute on a different thread!
  13391. </para>
  13392. <para>
  13393. Another implication is that since an Asio-aware fiber scheduler (not to mention
  13394. <link linkend="callbacks_asio"><code><phrase role="identifier">boost</phrase><phrase
  13395. role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
  13396. role="special">::</phrase><phrase role="identifier">asio</phrase><phrase
  13397. role="special">::</phrase><phrase role="identifier">yield</phrase></code></link>)
  13398. depends on handler calls from the <code><phrase role="identifier">io_service</phrase></code>,
  13399. it is the application&#8217;s responsibility to ensure that <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stop.html"><code><phrase
  13400. role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
  13401. role="identifier">stop</phrase><phrase role="special">()</phrase></code></ulink>
  13402. is not called until every fiber has terminated.
  13403. </para>
  13404. <para>
  13405. It is easier to reason about the behavior of the presented <code><phrase
  13406. role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
  13407. role="identifier">round_robin</phrase></code> scheduler if we require that
  13408. after initial setup, the thread&#8217;s main fiber is the fiber that calls <code><phrase
  13409. role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
  13410. role="identifier">run</phrase><phrase role="special">()</phrase></code>,
  13411. so let&#8217;s impose that requirement.
  13412. </para>
  13413. <para>
  13414. Naturally, the first thing we must do on each thread using a custom fiber
  13415. scheduler is call <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link>. However,
  13416. since <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
  13417. role="identifier">round_robin</phrase></code> requires an <code><phrase role="identifier">io_service</phrase></code>
  13418. instance, we must first declare that.
  13419. </para>
  13420. <para>
  13421. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">io_svc</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="special">&gt;();</phrase>
  13422. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">round_robin</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">);</phrase>
  13423. </programlisting>
  13424. </para>
  13425. <para>
  13426. <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
  13427. role="special">()</phrase></code> instantiates <code><phrase role="identifier">asio</phrase><phrase
  13428. role="special">::</phrase><phrase role="identifier">round_robin</phrase></code>,
  13429. which naturally calls its constructor:
  13430. </para>
  13431. <para>
  13432. <programlisting><phrase role="identifier">round_robin</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
  13433. <phrase role="identifier">io_svc_</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">),</phrase>
  13434. <phrase role="identifier">suspend_timer_</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13435. <phrase role="comment">// We use add_service() very deliberately. This will throw</phrase>
  13436. <phrase role="comment">// service_already_exists if you pass the same io_service instance to</phrase>
  13437. <phrase role="comment">// more than one round_robin instance.</phrase>
  13438. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">add_service</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">,</phrase> <phrase role="keyword">new</phrase> <phrase role="identifier">service</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  13439. <phrase role="identifier">io_svc_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">post</phrase><phrase role="special">([</phrase><phrase role="keyword">this</phrase><phrase role="special">]()</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase>
  13440. </programlisting>
  13441. </para>
  13442. <para>
  13443. <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
  13444. role="identifier">round_robin</phrase></code> binds the passed <code><phrase
  13445. role="identifier">io_service</phrase></code> pointer and initializes a <ulink
  13446. url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/steady_timer.html"><code><phrase
  13447. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  13448. role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
  13449. role="identifier">steady_timer</phrase></code></ulink>:
  13450. </para>
  13451. <para>
  13452. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">;</phrase>
  13453. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_timer</phrase> <phrase role="identifier">suspend_timer_</phrase><phrase role="special">;</phrase>
  13454. </programlisting>
  13455. </para>
  13456. <para>
  13457. Then it calls <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/add_service.html"><code><phrase
  13458. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  13459. role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
  13460. role="identifier">add_service</phrase><phrase role="special">()</phrase></code></ulink>
  13461. with a nested <code><phrase role="identifier">service</phrase></code> struct:
  13462. </para>
  13463. <para>
  13464. <programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">service</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">service</phrase> <phrase role="special">{</phrase>
  13465. <phrase role="keyword">static</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
  13466. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">work</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">work_</phrase><phrase role="special">;</phrase>
  13467. <phrase role="identifier">service</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
  13468. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">service</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">),</phrase>
  13469. <phrase role="identifier">work_</phrase><phrase role="special">{</phrase> <phrase role="keyword">new</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">work</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">)</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
  13470. <phrase role="special">}</phrase>
  13471. <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">service</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase>
  13472. <phrase role="identifier">service</phrase><phrase role="special">(</phrase> <phrase role="identifier">service</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  13473. <phrase role="identifier">service</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">service</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  13474. <phrase role="keyword">void</phrase> <phrase role="identifier">shutdown_service</phrase><phrase role="special">()</phrase> <phrase role="identifier">override</phrase> <phrase role="identifier">final</phrase> <phrase role="special">{</phrase>
  13475. <phrase role="identifier">work_</phrase><phrase role="special">.</phrase><phrase role="identifier">reset</phrase><phrase role="special">();</phrase>
  13476. <phrase role="special">}</phrase>
  13477. <phrase role="special">};</phrase>
  13478. </programlisting>
  13479. </para>
  13480. <para>
  13481. ... [asio_rr_service_bottom]
  13482. </para>
  13483. <para>
  13484. The <code><phrase role="identifier">service</phrase></code> struct has a
  13485. couple of roles.
  13486. </para>
  13487. <para>
  13488. Its foremost role is to manage a <literal>std::unique_ptr&lt;<ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service__work.html"><code><phrase
  13489. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  13490. role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
  13491. role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
  13492. role="identifier">work</phrase></code></ulink>&gt;</literal>. We want the
  13493. <code><phrase role="identifier">io_service</phrase></code> instance to continue
  13494. its main loop even when there is no pending Asio I/O.
  13495. </para>
  13496. <para>
  13497. But when <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service__service/shutdown_service.html"><code><phrase
  13498. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  13499. role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
  13500. role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
  13501. role="identifier">service</phrase><phrase role="special">::</phrase><phrase
  13502. role="identifier">shutdown_service</phrase><phrase role="special">()</phrase></code></ulink>
  13503. is called, we discard the <code><phrase role="identifier">io_service</phrase><phrase
  13504. role="special">::</phrase><phrase role="identifier">work</phrase></code>
  13505. instance so the <code><phrase role="identifier">io_service</phrase></code>
  13506. can shut down properly.
  13507. </para>
  13508. <para>
  13509. Its other purpose is to <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/post.html"><code><phrase
  13510. role="identifier">post</phrase><phrase role="special">()</phrase></code></ulink>
  13511. a lambda (not yet shown). Let&#8217;s walk further through the example program before
  13512. coming back to explain that lambda.
  13513. </para>
  13514. <para>
  13515. The <code><phrase role="identifier">service</phrase></code> constructor returns
  13516. to <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
  13517. role="identifier">round_robin</phrase></code>&#8217;s constructor, which returns
  13518. to <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
  13519. role="special">()</phrase></code>, which returns to the application code.
  13520. </para>
  13521. <para>
  13522. Once it has called <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
  13523. role="special">()</phrase></code>, the application may now launch some number
  13524. of fibers:
  13525. </para>
  13526. <para>
  13527. <programlisting><phrase role="comment">// server</phrase>
  13528. <phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">acceptor</phrase> <phrase role="identifier">a</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">,</phrase> <phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">endpoint</phrase><phrase role="special">(</phrase> <phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">v4</phrase><phrase role="special">(),</phrase> <phrase role="number">9999</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  13529. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">server</phrase><phrase role="special">,</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">a</phrase><phrase role="special">)</phrase> <phrase role="special">).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
  13530. <phrase role="comment">// client</phrase>
  13531. <phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="identifier">iterations</phrase> <phrase role="special">=</phrase> <phrase role="number">2</phrase><phrase role="special">;</phrase>
  13532. <phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="identifier">clients</phrase> <phrase role="special">=</phrase> <phrase role="number">3</phrase><phrase role="special">;</phrase>
  13533. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">barrier</phrase> <phrase role="identifier">b</phrase><phrase role="special">(</phrase> <phrase role="identifier">clients</phrase><phrase role="special">);</phrase>
  13534. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">clients</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13535. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase>
  13536. <phrase role="identifier">client</phrase><phrase role="special">,</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">a</phrase><phrase role="special">),</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">b</phrase><phrase role="special">),</phrase> <phrase role="identifier">iterations</phrase><phrase role="special">).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
  13537. <phrase role="special">}</phrase>
  13538. </programlisting>
  13539. </para>
  13540. <para>
  13541. Since we don&#8217;t specify a <link linkend="class_launch"><code>launch</code></link>, these fibers are ready to run,
  13542. but have not yet been entered.
  13543. </para>
  13544. <para>
  13545. Having set everything up, the application calls <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html"><code><phrase
  13546. role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
  13547. role="identifier">run</phrase><phrase role="special">()</phrase></code></ulink>:
  13548. </para>
  13549. <para>
  13550. <programlisting><phrase role="identifier">io_svc</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">run</phrase><phrase role="special">();</phrase>
  13551. </programlisting>
  13552. </para>
  13553. <para>
  13554. Now what?
  13555. </para>
  13556. <para>
  13557. Because this <code><phrase role="identifier">io_service</phrase></code> instance
  13558. owns an <code><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
  13559. role="identifier">work</phrase></code> instance, <code><phrase role="identifier">run</phrase><phrase
  13560. role="special">()</phrase></code> does not immediately return. But &mdash; none of
  13561. the fibers that will perform actual work has even been entered yet!
  13562. </para>
  13563. <para>
  13564. Without that initial <code><phrase role="identifier">post</phrase><phrase
  13565. role="special">()</phrase></code> call in <code><phrase role="identifier">service</phrase></code>&#8217;s
  13566. constructor, <emphasis>nothing</emphasis> would happen. The application would
  13567. hang right here.
  13568. </para>
  13569. <para>
  13570. So, what should the <code><phrase role="identifier">post</phrase><phrase
  13571. role="special">()</phrase></code> handler execute? Simply <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>?
  13572. </para>
  13573. <para>
  13574. That would be a promising start. But we have no guarantee that any of the
  13575. other fibers will initiate any Asio operations to keep the ball rolling.
  13576. For all we know, every other fiber could reach a similar <code><phrase role="identifier">boost</phrase><phrase
  13577. role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase
  13578. role="special">::</phrase><phrase role="identifier">yield</phrase><phrase
  13579. role="special">()</phrase></code> call first. Control would return to the
  13580. <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code>
  13581. handler, which would return to Asio, and... the application would hang.
  13582. </para>
  13583. <para>
  13584. The <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code>
  13585. handler could <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code>
  13586. itself again. But as discussed in <link linkend="embedded_main_loop">the
  13587. previous section</link>, once there are actual I/O operations in flight &mdash; once
  13588. we reach a state in which no fiber is ready &mdash;
  13589. that would cause the thread to
  13590. spin.
  13591. </para>
  13592. <para>
  13593. We could, of course, set an Asio timer &mdash; again as <link linkend="embedded_main_loop">previously
  13594. discussed</link>. But in this <quote>deeper dive,</quote> we&#8217;re trying to
  13595. do a little better.
  13596. </para>
  13597. <para>
  13598. The key to doing better is that since we&#8217;re in a fiber, we can run an actual
  13599. loop &mdash; not just a chain of callbacks. We can wait for <quote>something to happen</quote>
  13600. by calling <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run_one.html"><code><phrase
  13601. role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
  13602. role="identifier">run_one</phrase><phrase role="special">()</phrase></code></ulink>
  13603. &mdash; or we can execute already-queued Asio handlers by calling <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/poll.html"><code><phrase
  13604. role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
  13605. role="identifier">poll</phrase><phrase role="special">()</phrase></code></ulink>.
  13606. </para>
  13607. <para>
  13608. Here&#8217;s the body of the lambda passed to the <code><phrase role="identifier">post</phrase><phrase
  13609. role="special">()</phrase></code> call.
  13610. </para>
  13611. <para>
  13612. <programlisting> <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">stopped</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13613. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13614. <phrase role="comment">// run all pending handlers in round_robin</phrase>
  13615. <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">poll</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  13616. <phrase role="comment">// block this fiber till all pending (ready) fibers are processed</phrase>
  13617. <phrase role="comment">// == round_robin::suspend_until() has been called</phrase>
  13618. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">);</phrase>
  13619. <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
  13620. <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
  13621. <phrase role="comment">// run one handler inside io_service</phrase>
  13622. <phrase role="comment">// if no handler available, block this thread</phrase>
  13623. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">run_one</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13624. <phrase role="keyword">break</phrase><phrase role="special">;</phrase>
  13625. <phrase role="special">}</phrase>
  13626. <phrase role="special">}</phrase>
  13627. <phrase role="special">}</phrase>
  13628. </programlisting>
  13629. </para>
  13630. <para>
  13631. We want this loop to exit once the <code><phrase role="identifier">io_service</phrase></code>
  13632. instance has been <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stopped.html"><code><phrase
  13633. role="identifier">stopped</phrase><phrase role="special">()</phrase></code></ulink>.
  13634. </para>
  13635. <para>
  13636. As long as there are ready fibers, we interleave running ready Asio handlers
  13637. with running ready fibers.
  13638. </para>
  13639. <para>
  13640. If there are no ready fibers, we wait by calling <code><phrase role="identifier">run_one</phrase><phrase
  13641. role="special">()</phrase></code>. Once any Asio handler has been called
  13642. &mdash; no matter which &mdash; <code><phrase role="identifier">run_one</phrase><phrase role="special">()</phrase></code>
  13643. returns. That handler may have transitioned some fiber to ready state, so
  13644. we loop back to check again.
  13645. </para>
  13646. <para>
  13647. (We won&#8217;t describe <code><phrase role="identifier">awakened</phrase><phrase
  13648. role="special">()</phrase></code>, <code><phrase role="identifier">pick_next</phrase><phrase
  13649. role="special">()</phrase></code> or <code><phrase role="identifier">has_ready_fibers</phrase><phrase
  13650. role="special">()</phrase></code>, as these are just like <link linkend="round_robin_awakened"><code>round_robin::awakened()</code></link>,
  13651. <link linkend="round_robin_pick_next"><code>round_robin::pick_next()</code></link> and <link linkend="round_robin_has_ready_fibers"><code>round_robin::has_ready_fibers()</code></link>.)
  13652. </para>
  13653. <para>
  13654. That leaves <code><phrase role="identifier">suspend_until</phrase><phrase
  13655. role="special">()</phrase></code> and <code><phrase role="identifier">notify</phrase><phrase
  13656. role="special">()</phrase></code>.
  13657. </para>
  13658. <para>
  13659. Doubtless you have been asking yourself: why are we calling <code><phrase
  13660. role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
  13661. role="identifier">run_one</phrase><phrase role="special">()</phrase></code>
  13662. in the lambda loop? Why not call it in <code><phrase role="identifier">suspend_until</phrase><phrase
  13663. role="special">()</phrase></code>, whose very API was designed for just such
  13664. a purpose?
  13665. </para>
  13666. <para>
  13667. Under normal circumstances, when the fiber manager finds no ready fibers,
  13668. it calls <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>. Why test <code><phrase
  13669. role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase></code>
  13670. in the lambda loop? Why not leverage the normal mechanism?
  13671. </para>
  13672. <para>
  13673. The answer is: it matters who&#8217;s asking.
  13674. </para>
  13675. <para>
  13676. Consider the lambda loop shown above. The only <emphasis role="bold">Boost.Fiber</emphasis>
  13677. APIs it engages are <code><phrase role="identifier">has_ready_fibers</phrase><phrase
  13678. role="special">()</phrase></code> and <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>.
  13679. <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>
  13680. does not <emphasis>block</emphasis> the calling fiber: the calling fiber
  13681. does not become unready. It is immediately passed back to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>,
  13682. to be resumed in its turn when all other ready fibers have had a chance to
  13683. run. In other words: during a <code><phrase role="identifier">yield</phrase><phrase
  13684. role="special">()</phrase></code> call, <emphasis>there is always at least
  13685. one ready fiber.</emphasis>
  13686. </para>
  13687. <para>
  13688. As long as this lambda loop is still running, the fiber manager does not
  13689. call <code><phrase role="identifier">suspend_until</phrase><phrase role="special">()</phrase></code>
  13690. because it always has a fiber ready to run.
  13691. </para>
  13692. <para>
  13693. However, the lambda loop <emphasis>itself</emphasis> can detect the case
  13694. when no <emphasis>other</emphasis> fibers are ready to run: the running fiber
  13695. is not <emphasis>ready</emphasis> but <emphasis>running.</emphasis>
  13696. </para>
  13697. <para>
  13698. That said, <code><phrase role="identifier">suspend_until</phrase><phrase
  13699. role="special">()</phrase></code> and <code><phrase role="identifier">notify</phrase><phrase
  13700. role="special">()</phrase></code> are in fact called during orderly shutdown
  13701. processing, so let&#8217;s try a plausible implementation.
  13702. </para>
  13703. <para>
  13704. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
  13705. <phrase role="comment">// Set a timer so at least one handler will eventually fire, causing</phrase>
  13706. <phrase role="comment">// run_one() to eventually return.</phrase>
  13707. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">::</phrase><phrase role="identifier">max</phrase><phrase role="special">)()</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  13708. <phrase role="comment">// Each expires_at(time_point) call cancels any previous pending</phrase>
  13709. <phrase role="comment">// call. We could inadvertently spin like this:</phrase>
  13710. <phrase role="comment">// dispatcher calls suspend_until() with earliest wake time</phrase>
  13711. <phrase role="comment">// suspend_until() sets suspend_timer_</phrase>
  13712. <phrase role="comment">// lambda loop calls run_one()</phrase>
  13713. <phrase role="comment">// some other asio handler runs before timer expires</phrase>
  13714. <phrase role="comment">// run_one() returns to lambda loop</phrase>
  13715. <phrase role="comment">// lambda loop yields to dispatcher</phrase>
  13716. <phrase role="comment">// dispatcher finds no ready fibers</phrase>
  13717. <phrase role="comment">// dispatcher calls suspend_until() with SAME wake time</phrase>
  13718. <phrase role="comment">// suspend_until() sets suspend_timer_ to same time, canceling</phrase>
  13719. <phrase role="comment">// previous async_wait()</phrase>
  13720. <phrase role="comment">// lambda loop calls run_one()</phrase>
  13721. <phrase role="comment">// asio calls suspend_timer_ handler with operation_aborted</phrase>
  13722. <phrase role="comment">// run_one() returns to lambda loop... etc. etc.</phrase>
  13723. <phrase role="comment">// So only actually set the timer when we're passed a DIFFERENT</phrase>
  13724. <phrase role="comment">// abs_time value.</phrase>
  13725. <phrase role="identifier">suspend_timer_</phrase><phrase role="special">.</phrase><phrase role="identifier">expires_at</phrase><phrase role="special">(</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">);</phrase>
  13726. <phrase role="identifier">suspend_timer_</phrase><phrase role="special">.</phrase><phrase role="identifier">async_wait</phrase><phrase role="special">([](</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;){</phrase>
  13727. <phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
  13728. <phrase role="special">});</phrase>
  13729. <phrase role="special">}</phrase>
  13730. <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase>
  13731. <phrase role="special">}</phrase>
  13732. </programlisting>
  13733. </para>
  13734. <para>
  13735. As you might expect, <code><phrase role="identifier">suspend_until</phrase><phrase
  13736. role="special">()</phrase></code> sets an <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/steady_timer.html"><code><phrase
  13737. role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
  13738. role="identifier">steady_timer</phrase></code></ulink> to <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/basic_waitable_timer/expires_at.html"><code><phrase
  13739. role="identifier">expires_at</phrase><phrase role="special">()</phrase></code></ulink>
  13740. the passed <ulink url="http://en.cppreference.com/w/cpp/chrono/steady_clock"><code><phrase
  13741. role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase
  13742. role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase
  13743. role="special">::</phrase><phrase role="identifier">time_point</phrase></code></ulink>.
  13744. Usually.
  13745. </para>
  13746. <para>
  13747. As indicated in comments, we avoid setting <code><phrase role="identifier">suspend_timer_</phrase></code>
  13748. multiple times to the <emphasis>same</emphasis> <code><phrase role="identifier">time_point</phrase></code>
  13749. value since every <code><phrase role="identifier">expires_at</phrase><phrase
  13750. role="special">()</phrase></code> call cancels any previous <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/basic_waitable_timer/async_wait.html"><code><phrase
  13751. role="identifier">async_wait</phrase><phrase role="special">()</phrase></code></ulink>
  13752. call. There is a chance that we could spin. Reaching <code><phrase role="identifier">suspend_until</phrase><phrase
  13753. role="special">()</phrase></code> means the fiber manager intends to yield
  13754. the processor to Asio. Cancelling the previous <code><phrase role="identifier">async_wait</phrase><phrase
  13755. role="special">()</phrase></code> call would fire its handler, causing <code><phrase
  13756. role="identifier">run_one</phrase><phrase role="special">()</phrase></code>
  13757. to return, potentially causing the fiber manager to call <code><phrase role="identifier">suspend_until</phrase><phrase
  13758. role="special">()</phrase></code> again with the same <code><phrase role="identifier">time_point</phrase></code>
  13759. value...
  13760. </para>
  13761. <para>
  13762. Given that we suspend the thread by calling <code><phrase role="identifier">io_service</phrase><phrase
  13763. role="special">::</phrase><phrase role="identifier">run_one</phrase><phrase
  13764. role="special">()</phrase></code>, what&#8217;s important is that our <code><phrase
  13765. role="identifier">async_wait</phrase><phrase role="special">()</phrase></code>
  13766. call will cause a handler to run, which will cause <code><phrase role="identifier">run_one</phrase><phrase
  13767. role="special">()</phrase></code> to return. It&#8217;s not so important specifically
  13768. what that handler does.
  13769. </para>
  13770. <para>
  13771. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
  13772. <phrase role="comment">// Something has happened that should wake one or more fibers BEFORE</phrase>
  13773. <phrase role="comment">// suspend_timer_ expires. Reset the timer to cause it to fire</phrase>
  13774. <phrase role="comment">// immediately, causing the run_one() call to return. In theory we</phrase>
  13775. <phrase role="comment">// could use cancel() because we don't care whether suspend_timer_'s</phrase>
  13776. <phrase role="comment">// handler is called with operation_aborted or success. However --</phrase>
  13777. <phrase role="comment">// cancel() doesn't change the expiration time, and we use</phrase>
  13778. <phrase role="comment">// suspend_timer_'s expiration time to decide whether it's already</phrase>
  13779. <phrase role="comment">// set. If suspend_until() set some specific wake time, then notify()</phrase>
  13780. <phrase role="comment">// canceled it, then suspend_until() was called again with the same</phrase>
  13781. <phrase role="comment">// wake time, it would match suspend_timer_'s expiration time and we'd</phrase>
  13782. <phrase role="comment">// refrain from setting the timer. So instead of simply calling</phrase>
  13783. <phrase role="comment">// cancel(), reset the timer, which cancels the pending sleep AND sets</phrase>
  13784. <phrase role="comment">// a new expiration time. This will cause us to spin the loop twice --</phrase>
  13785. <phrase role="comment">// once for the operation_aborted handler, once for timer expiration</phrase>
  13786. <phrase role="comment">// -- but that shouldn't be a big problem.</phrase>
  13787. <phrase role="identifier">suspend_timer_</phrase><phrase role="special">.</phrase><phrase role="identifier">async_wait</phrase><phrase role="special">([](</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;){</phrase>
  13788. <phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
  13789. <phrase role="special">});</phrase>
  13790. <phrase role="identifier">suspend_timer_</phrase><phrase role="special">.</phrase><phrase role="identifier">expires_at</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">now</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  13791. <phrase role="special">}</phrase>
  13792. </programlisting>
  13793. </para>
  13794. <para>
  13795. Since an <code><phrase role="identifier">expires_at</phrase><phrase role="special">()</phrase></code>
  13796. call cancels any previous <code><phrase role="identifier">async_wait</phrase><phrase
  13797. role="special">()</phrase></code> call, we can make <code><phrase role="identifier">notify</phrase><phrase
  13798. role="special">()</phrase></code> simply call <code><phrase role="identifier">steady_timer</phrase><phrase
  13799. role="special">::</phrase><phrase role="identifier">expires_at</phrase><phrase
  13800. role="special">()</phrase></code>. That should cause the <code><phrase role="identifier">io_service</phrase></code>
  13801. to call the <code><phrase role="identifier">async_wait</phrase><phrase role="special">()</phrase></code>
  13802. handler with <code><phrase role="identifier">operation_aborted</phrase></code>.
  13803. </para>
  13804. <para>
  13805. The comments in <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code>
  13806. explain why we call <code><phrase role="identifier">expires_at</phrase><phrase
  13807. role="special">()</phrase></code> rather than <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/basic_waitable_timer/cancel.html"><code><phrase
  13808. role="identifier">cancel</phrase><phrase role="special">()</phrase></code></ulink>.
  13809. </para>
  13810. <para>
  13811. This <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
  13812. role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase
  13813. role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
  13814. role="identifier">round_robin</phrase></code> implementation is used in
  13815. <ulink url="../../examples/asio/autoecho.cpp"><code><phrase role="identifier">examples</phrase><phrase
  13816. role="special">/</phrase><phrase role="identifier">asio</phrase><phrase role="special">/</phrase><phrase
  13817. role="identifier">autoecho</phrase><phrase role="special">.</phrase><phrase
  13818. role="identifier">cpp</phrase></code></ulink>.
  13819. </para>
  13820. <para>
  13821. It seems possible that you could put together a more elegant Fiber / Asio
  13822. integration. But as noted at the outset: it&#8217;s tricky.
  13823. </para>
  13824. </section>
  13825. </section>
  13826. <section id="fiber.speculation">
  13827. <title><anchor id="speculation"/><link linkend="fiber.speculation">Specualtive
  13828. execution</link></title>
  13829. <bridgehead renderas="sect3" id="fiber.speculation.h0">
  13830. <phrase id="fiber.speculation.hardware_transactional_memory"/><link linkend="fiber.speculation.hardware_transactional_memory">Hardware
  13831. transactional memory</link>
  13832. </bridgehead>
  13833. <para>
  13834. With help of hardware transactional memory multiple logical processors execute
  13835. a critical region speculatively, e.g. without explicit synchronization.<sbr/>
  13836. If the transactional execution completes successfully, then all memory operations
  13837. performed within the transactional region are commited without any inter-thread
  13838. serialization.<sbr/> When the optimistic execution fails, the processor aborts
  13839. the transaction and discards all performed modifications.<sbr/> In non-transactional
  13840. code a single lock serializes the access to a critical region. With a transactional
  13841. memory, multiple logical processor start a transaction and update the memory
  13842. (the data) inside the ciritical region. Unless some logical processors try
  13843. to update the same data, the transactions would always succeed.
  13844. </para>
  13845. <bridgehead renderas="sect3" id="fiber.speculation.h1">
  13846. <phrase id="fiber.speculation.intel_transactional_synchronisation_extensions__tsx_"/><link
  13847. linkend="fiber.speculation.intel_transactional_synchronisation_extensions__tsx_">Intel
  13848. Transactional Synchronisation Extensions (TSX)</link>
  13849. </bridgehead>
  13850. <para>
  13851. TSX is Intel's implementation of hardware transactional memory in modern Intel
  13852. processors<footnote id="fiber.speculation.f0">
  13853. <para>
  13854. intel.com: <ulink url="https://software.intel.com/en-us/node/695149">Intel
  13855. Transactional Synchronization Extensions</ulink>
  13856. </para>
  13857. </footnote>.<sbr/> In TSX the hardware keeps track of which cachelines have
  13858. been read from and which have been written to in a transaction. The cache-line
  13859. size (64-byte) and the n-way set associative cache determine the maximum size
  13860. of memory in a transaction. For instance if a transaction modifies 9 cache-lines
  13861. at a processor with a 8-way set associative cache, the transaction will always
  13862. be aborted.
  13863. </para>
  13864. <note>
  13865. <para>
  13866. TXS is enabled if property <code><phrase role="identifier">htm</phrase><phrase
  13867. role="special">=</phrase><phrase role="identifier">tsx</phrase></code> is
  13868. specified at b2 command-line and <code><phrase role="identifier">BOOST_USE_TSX</phrase></code>
  13869. is applied to the compiler.
  13870. </para>
  13871. </note>
  13872. <note>
  13873. <para>
  13874. A TSX-transaction will be aborted if the floating point state is modified
  13875. inside a critical region. As a consequence floating point operations, e.g.
  13876. store/load of floating point related registers during a fiber (context) switch
  13877. are disabled.
  13878. </para>
  13879. </note>
  13880. <important>
  13881. <para>
  13882. TSX can not be used together with MSVC at this time!
  13883. </para>
  13884. </important>
  13885. <para>
  13886. Boost.Fiber uses TSX-enabled spinlocks to protect critical regions (see section
  13887. <link linkend="tuning">Tuning</link>).
  13888. </para>
  13889. </section>
  13890. <section id="fiber.numa">
  13891. <title><anchor id="numa"/><link linkend="fiber.numa">NUMA</link></title>
  13892. <para>
  13893. Modern micro-processors contain integrated memory controllers that are connected
  13894. via channels to the memory. Accessing the memory can be organized in two kinds:<sbr/>
  13895. Uniform Memory Access (UMA) and Non-Uniform Memory Access (NUMA).
  13896. </para>
  13897. <para>
  13898. In contrast to UMA, that provides a centralized pool of memory (and thus does
  13899. not scale after a certain number of processors), a NUMA architecture divides
  13900. the memory into local and remote memory relative to the micro-processor.<sbr/>
  13901. Local memory is directly attached to the processor's integrated memory controller.
  13902. Memory connected to the memory controller of another micro-processor (multi-socket
  13903. systems) is considered as remote memory. If a memory controller access remote
  13904. memory it has to traverse the interconnect<footnote id="fiber.numa.f0">
  13905. <para>
  13906. On x86 the interconnection is implemented by Intel's Quick Path Interconnect
  13907. (QPI) and AMD's HyperTransport.
  13908. </para>
  13909. </footnote> and connect to the remote memory controller.<sbr/> Thus accessing
  13910. remote memory adds additional latency overhead to local memory access. Because
  13911. of the different memory locations, a NUMA-system experiences <emphasis>non-uniform</emphasis>
  13912. memory access time.<sbr/> As a consequence the best performance is achieved
  13913. by keeping the memory access local.
  13914. </para>
  13915. <para>
  13916. <inlinemediaobject><imageobject><imagedata align="center" fileref="../../../../libs/fiber/doc/NUMA.png"></imagedata></imageobject>
  13917. <textobject>
  13918. <phrase>NUMA</phrase>
  13919. </textobject>
  13920. </inlinemediaobject>
  13921. </para>
  13922. <bridgehead renderas="sect3" id="fiber.numa.h0">
  13923. <phrase id="fiber.numa.numa_support_in_boost_fiber"/><link linkend="fiber.numa.numa_support_in_boost_fiber">NUMA
  13924. support in Boost.Fiber</link>
  13925. </bridgehead>
  13926. <para>
  13927. Because only a subset of the NUMA-functionality is exposed by several operating
  13928. systems, Boost.Fiber provides only a minimalistic NUMA API.
  13929. </para>
  13930. <important>
  13931. <para>
  13932. In order to enable NUMA support, b2 property <code><phrase role="identifier">numa</phrase><phrase
  13933. role="special">=</phrase><phrase role="identifier">on</phrase></code> must
  13934. be specified and linked against additional library <code><phrase role="identifier">libboost_fiber_numa</phrase><phrase
  13935. role="special">.</phrase><phrase role="identifier">so</phrase></code>.
  13936. </para>
  13937. </important>
  13938. <important>
  13939. <para>
  13940. MinGW using pthread implementation is not supported on Windows.
  13941. </para>
  13942. </important>
  13943. <table frame="all" id="fiber.numa.supported_functionality_operating_systems">
  13944. <title>Supported functionality/operating systems</title>
  13945. <tgroup cols="7">
  13946. <thead>
  13947. <row>
  13948. <entry>
  13949. </entry>
  13950. <entry>
  13951. <para>
  13952. AIX
  13953. </para>
  13954. </entry>
  13955. <entry>
  13956. <para>
  13957. FreeBSD
  13958. </para>
  13959. </entry>
  13960. <entry>
  13961. <para>
  13962. HP/UX
  13963. </para>
  13964. </entry>
  13965. <entry>
  13966. <para>
  13967. Linux
  13968. </para>
  13969. </entry>
  13970. <entry>
  13971. <para>
  13972. Solaris
  13973. </para>
  13974. </entry>
  13975. <entry>
  13976. <para>
  13977. Windows
  13978. </para>
  13979. </entry>
  13980. </row>
  13981. </thead>
  13982. <tbody>
  13983. <row>
  13984. <entry>
  13985. <para>
  13986. pin thread
  13987. </para>
  13988. </entry>
  13989. <entry>
  13990. <para>
  13991. +
  13992. </para>
  13993. </entry>
  13994. <entry>
  13995. <para>
  13996. +
  13997. </para>
  13998. </entry>
  13999. <entry>
  14000. <para>
  14001. +
  14002. </para>
  14003. </entry>
  14004. <entry>
  14005. <para>
  14006. +
  14007. </para>
  14008. </entry>
  14009. <entry>
  14010. <para>
  14011. +
  14012. </para>
  14013. </entry>
  14014. <entry>
  14015. <para>
  14016. +
  14017. </para>
  14018. </entry>
  14019. </row>
  14020. <row>
  14021. <entry>
  14022. <para>
  14023. logical CPUs/NUMA nodes
  14024. </para>
  14025. </entry>
  14026. <entry>
  14027. <para>
  14028. +
  14029. </para>
  14030. </entry>
  14031. <entry>
  14032. <para>
  14033. +
  14034. </para>
  14035. </entry>
  14036. <entry>
  14037. <para>
  14038. +
  14039. </para>
  14040. </entry>
  14041. <entry>
  14042. <para>
  14043. +
  14044. </para>
  14045. </entry>
  14046. <entry>
  14047. <para>
  14048. +
  14049. </para>
  14050. </entry>
  14051. <entry>
  14052. <para>
  14053. +<footnote id="fiber.numa.f1">
  14054. <para>
  14055. Windows organizes logical cpus in groups of 64; boost.fiber maps
  14056. {group-id,cpud-id} to a scalar equivalent to cpu ID of Linux (64
  14057. * group ID + cpu ID).
  14058. </para>
  14059. </footnote>
  14060. </para>
  14061. </entry>
  14062. </row>
  14063. <row>
  14064. <entry>
  14065. <para>
  14066. NUMA node distance
  14067. </para>
  14068. </entry>
  14069. <entry>
  14070. <para>
  14071. -
  14072. </para>
  14073. </entry>
  14074. <entry>
  14075. <para>
  14076. -
  14077. </para>
  14078. </entry>
  14079. <entry>
  14080. <para>
  14081. -
  14082. </para>
  14083. </entry>
  14084. <entry>
  14085. <para>
  14086. +
  14087. </para>
  14088. </entry>
  14089. <entry>
  14090. <para>
  14091. -
  14092. </para>
  14093. </entry>
  14094. <entry>
  14095. <para>
  14096. -
  14097. </para>
  14098. </entry>
  14099. </row>
  14100. <row>
  14101. <entry>
  14102. <para>
  14103. tested on
  14104. </para>
  14105. </entry>
  14106. <entry>
  14107. <para>
  14108. AIX 7.2
  14109. </para>
  14110. </entry>
  14111. <entry>
  14112. <para>
  14113. FreeBSD 11
  14114. </para>
  14115. </entry>
  14116. <entry>
  14117. <para>
  14118. -
  14119. </para>
  14120. </entry>
  14121. <entry>
  14122. <para>
  14123. Arch Linux (4.10.13)
  14124. </para>
  14125. </entry>
  14126. <entry>
  14127. <para>
  14128. OpenIndiana HIPSTER
  14129. </para>
  14130. </entry>
  14131. <entry>
  14132. <para>
  14133. Windows 10
  14134. </para>
  14135. </entry>
  14136. </row>
  14137. </tbody>
  14138. </tgroup>
  14139. </table>
  14140. <para>
  14141. In order to keep the memory access local as possible, the NUMA topology must
  14142. be evaluated.
  14143. </para>
  14144. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">topo</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">topology</phrase><phrase role="special">();</phrase>
  14145. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">auto</phrase> <phrase role="identifier">n</phrase> <phrase role="special">:</phrase> <phrase role="identifier">topo</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14146. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;node: &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">n</phrase><phrase role="special">.</phrase><phrase role="identifier">id</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; | &quot;</phrase><phrase role="special">;</phrase>
  14147. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;cpus: &quot;</phrase><phrase role="special">;</phrase>
  14148. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">auto</phrase> <phrase role="identifier">cpu_id</phrase> <phrase role="special">:</phrase> <phrase role="identifier">n</phrase><phrase role="special">.</phrase><phrase role="identifier">logical_cpus</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14149. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">cpu_id</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; &quot;</phrase><phrase role="special">;</phrase>
  14150. <phrase role="special">}</phrase>
  14151. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;| distance: &quot;</phrase><phrase role="special">;</phrase>
  14152. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">auto</phrase> <phrase role="identifier">d</phrase> <phrase role="special">:</phrase> <phrase role="identifier">n</phrase><phrase role="special">.</phrase><phrase role="identifier">distance</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14153. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">d</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; &quot;</phrase><phrase role="special">;</phrase>
  14154. <phrase role="special">}</phrase>
  14155. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  14156. <phrase role="special">}</phrase>
  14157. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;done&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  14158. <phrase role="identifier">output</phrase><phrase role="special">:</phrase>
  14159. <phrase role="identifier">node</phrase><phrase role="special">:</phrase> <phrase role="number">0</phrase> <phrase role="special">|</phrase> <phrase role="identifier">cpus</phrase><phrase role="special">:</phrase> <phrase role="number">0</phrase> <phrase role="number">1</phrase> <phrase role="number">2</phrase> <phrase role="number">3</phrase> <phrase role="number">4</phrase> <phrase role="number">5</phrase> <phrase role="number">6</phrase> <phrase role="number">7</phrase> <phrase role="number">16</phrase> <phrase role="number">17</phrase> <phrase role="number">18</phrase> <phrase role="number">19</phrase> <phrase role="number">20</phrase> <phrase role="number">21</phrase> <phrase role="number">22</phrase> <phrase role="number">23</phrase> <phrase role="special">|</phrase> <phrase role="identifier">distance</phrase><phrase role="special">:</phrase> <phrase role="number">10</phrase> <phrase role="number">21</phrase>
  14160. <phrase role="identifier">node</phrase><phrase role="special">:</phrase> <phrase role="number">1</phrase> <phrase role="special">|</phrase> <phrase role="identifier">cpus</phrase><phrase role="special">:</phrase> <phrase role="number">8</phrase> <phrase role="number">9</phrase> <phrase role="number">10</phrase> <phrase role="number">11</phrase> <phrase role="number">12</phrase> <phrase role="number">13</phrase> <phrase role="number">14</phrase> <phrase role="number">15</phrase> <phrase role="number">24</phrase> <phrase role="number">25</phrase> <phrase role="number">26</phrase> <phrase role="number">27</phrase> <phrase role="number">28</phrase> <phrase role="number">29</phrase> <phrase role="number">30</phrase> <phrase role="number">31</phrase> <phrase role="special">|</phrase> <phrase role="identifier">distance</phrase><phrase role="special">:</phrase> <phrase role="number">21</phrase> <phrase role="number">10</phrase>
  14161. <phrase role="identifier">done</phrase>
  14162. </programlisting>
  14163. <para>
  14164. The example shows that the systems consits out of 2 NUMA-nodes, to each NUMA-node
  14165. belong 16 logical cpus. The distance measures the costs to access the memory
  14166. of another NUMA-node. A NUMA-node has always a distance <code><phrase role="number">10</phrase></code>
  14167. to itself (lowest possible value).<sbr/> The position in the array corresponds
  14168. with the NUMA-node ID.
  14169. </para>
  14170. <para>
  14171. Some work-loads benefit from pinning threads to a logical cpus. For instance
  14172. scheduling algorithm <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link> pins the thread
  14173. that runs the fiber scheduler to a logical cpu. This prevents the operating
  14174. system scheduler to move the thread to another logical cpu that might run other
  14175. fiber scheduler(s) or migrating the thread to a logical cpu part of another
  14176. NUMA-node.
  14177. </para>
  14178. <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">node_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">topo</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14179. <phrase role="comment">// thread registers itself at work-stealing scheduler</phrase>
  14180. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">node_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">topo</phrase><phrase role="special">);</phrase>
  14181. <phrase role="special">...</phrase>
  14182. <phrase role="special">}</phrase>
  14183. <phrase role="comment">// evaluate the NUMA topology</phrase>
  14184. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">topo</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">topology</phrase><phrase role="special">();</phrase>
  14185. <phrase role="comment">// start-thread runs on NUMA-node `0`</phrase>
  14186. <phrase role="keyword">auto</phrase> <phrase role="identifier">node</phrase> <phrase role="special">=</phrase> <phrase role="identifier">topo</phrase><phrase role="special">[</phrase><phrase role="number">0</phrase><phrase role="special">];</phrase>
  14187. <phrase role="comment">// start-thread is pinnded to first cpu ID in the list of logical cpus of NUMA-node `0`</phrase>
  14188. <phrase role="keyword">auto</phrase> <phrase role="identifier">start_cpu_id</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase> <phrase role="identifier">node</phrase><phrase role="special">.</phrase><phrase role="identifier">logical_cpus</phrase><phrase role="special">.</phrase><phrase role="identifier">begin</phrase><phrase role="special">();</phrase>
  14189. <phrase role="comment">// start worker-threads first</phrase>
  14190. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">threads</phrase><phrase role="special">;</phrase>
  14191. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">auto</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">node</phrase> <phrase role="special">:</phrase> <phrase role="identifier">topo</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14192. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase> <phrase role="special">:</phrase> <phrase role="identifier">node</phrase><phrase role="special">.</phrase><phrase role="identifier">logical_cpus</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14193. <phrase role="comment">// exclude start-thread</phrase>
  14194. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">start_cpu_id</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14195. <phrase role="comment">// spawn thread</phrase>
  14196. <phrase role="identifier">threads</phrase><phrase role="special">.</phrase><phrase role="identifier">emplace_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">node</phrase><phrase role="special">.</phrase><phrase role="identifier">id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cref</phrase><phrase role="special">(</phrase> <phrase role="identifier">topo</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  14197. <phrase role="special">}</phrase>
  14198. <phrase role="special">}</phrase>
  14199. <phrase role="special">}</phrase>
  14200. <phrase role="comment">// start-thread registers itself on work-stealing scheduler</phrase>
  14201. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">start_cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">node</phrase><phrase role="special">.</phrase><phrase role="identifier">id</phrase><phrase role="special">,</phrase> <phrase role="identifier">topo</phrase><phrase role="special">);</phrase>
  14202. <phrase role="special">...</phrase>
  14203. </programlisting>
  14204. <para>
  14205. The example evaluates the NUMA topology with <code><phrase role="identifier">boost</phrase><phrase
  14206. role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
  14207. role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase
  14208. role="identifier">topology</phrase><phrase role="special">()</phrase></code>
  14209. and spawns for each logical cpu a thread. Each spawned thread installs the
  14210. NUMA-aware work-stealing scheduler. The scheduler pins the thread to the logical
  14211. cpu that was specified at construction.<sbr/> If the local queue of one thread
  14212. runs out of ready fibers, the thread tries to steal a ready fiber from another
  14213. thread running at logical cpu that belong to the same NUMA-node (local memory
  14214. access). If no fiber could be stolen, the thread tries to steal fibers from
  14215. logical cpus part of other NUMA-nodes (remote memory access).
  14216. </para>
  14217. <bridgehead renderas="sect3" id="fiber.numa.h1">
  14218. <phrase id="fiber.numa.synopsis"/><link linkend="fiber.numa.synopsis">Synopsis</link>
  14219. </bridgehead>
  14220. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">pin_thread</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  14221. <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">topology</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  14222. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  14223. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  14224. <phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
  14225. <phrase role="keyword">struct</phrase> <phrase role="identifier">node</phrase> <phrase role="special">{</phrase>
  14226. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
  14227. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">logical_cpus</phrase><phrase role="special">;</phrase>
  14228. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">distance</phrase><phrase role="special">;</phrase>
  14229. <phrase role="special">};</phrase>
  14230. <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  14231. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">topology</phrase><phrase role="special">();</phrase>
  14232. <phrase role="keyword">void</phrase> <phrase role="identifier">pin_thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase><phrase role="special">);</phrase>
  14233. <phrase role="keyword">void</phrase> <phrase role="identifier">pin_thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">native_handle_type</phrase><phrase role="special">);</phrase>
  14234. <phrase role="special">}}}</phrase>
  14235. <phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">algo</phrase><phrase role="special">/</phrase><phrase role="identifier">work_stealing</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  14236. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  14237. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  14238. <phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
  14239. <phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
  14240. <phrase role="keyword">class</phrase> <phrase role="identifier">work_stealing</phrase><phrase role="special">;</phrase>
  14241. <phrase role="special">}}}</phrase>
  14242. </programlisting>
  14243. <para>
  14244. <bridgehead renderas="sect4" id="class_numa_node_bridgehead">
  14245. <phrase id="class_numa_node"/>
  14246. <link linkend="class_numa_node">Class <code>numa::node</code></link>
  14247. </bridgehead>
  14248. </para>
  14249. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">topology</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  14250. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  14251. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  14252. <phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
  14253. <phrase role="keyword">struct</phrase> <phrase role="identifier">node</phrase> <phrase role="special">{</phrase>
  14254. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
  14255. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">logical_cpus</phrase><phrase role="special">;</phrase>
  14256. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">distance</phrase><phrase role="special">;</phrase>
  14257. <phrase role="special">};</phrase>
  14258. <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  14259. <phrase role="special">}}}</phrase>
  14260. </programlisting>
  14261. <para>
  14262. <bridgehead renderas="sect4" id="numa_node_id_bridgehead">
  14263. <phrase id="numa_node_id"/>
  14264. <link linkend="numa_node_id">Data member <code>id</code></link>
  14265. </bridgehead>
  14266. </para>
  14267. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
  14268. </programlisting>
  14269. <variablelist>
  14270. <title></title>
  14271. <varlistentry>
  14272. <term>Effects:</term>
  14273. <listitem>
  14274. <para>
  14275. ID of the NUMA-node
  14276. </para>
  14277. </listitem>
  14278. </varlistentry>
  14279. </variablelist>
  14280. <para>
  14281. <bridgehead renderas="sect4" id="numa_node_logical_cpus_bridgehead">
  14282. <phrase id="numa_node_logical_cpus"/>
  14283. <link linkend="numa_node_logical_cpus">Data
  14284. member <code>logical_cpus</code></link>
  14285. </bridgehead>
  14286. </para>
  14287. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">logical_cpus</phrase><phrase role="special">;</phrase>
  14288. </programlisting>
  14289. <variablelist>
  14290. <title></title>
  14291. <varlistentry>
  14292. <term>Effects:</term>
  14293. <listitem>
  14294. <para>
  14295. set of logical cpu IDs belonging to the NUMA-node
  14296. </para>
  14297. </listitem>
  14298. </varlistentry>
  14299. </variablelist>
  14300. <para>
  14301. <bridgehead renderas="sect4" id="numa_node_distance_bridgehead">
  14302. <phrase id="numa_node_distance"/>
  14303. <link linkend="numa_node_distance">Data member
  14304. <code>distance</code></link>
  14305. </bridgehead>
  14306. </para>
  14307. <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">distance</phrase><phrase role="special">;</phrase>
  14308. </programlisting>
  14309. <variablelist>
  14310. <title></title>
  14311. <varlistentry>
  14312. <term>Effects:</term>
  14313. <listitem>
  14314. <para>
  14315. The distance between NUMA-nodes describe the cots of accessing the remote
  14316. memory.
  14317. </para>
  14318. </listitem>
  14319. </varlistentry>
  14320. <varlistentry>
  14321. <term>Note:</term>
  14322. <listitem>
  14323. <para>
  14324. A NUMA-node has a distance of <code><phrase role="number">10</phrase></code>
  14325. to itself, remote NUMA-nodes have a distance &gt; <code><phrase role="number">10</phrase></code>.
  14326. The index in the array corresponds to the ID <code><phrase role="identifier">id</phrase></code>
  14327. of the NUMA-node. At the moment only Linux returns the correct distances,
  14328. for all other operating systems remote NUMA-nodes get a default value
  14329. of <code><phrase role="number">20</phrase></code>.
  14330. </para>
  14331. </listitem>
  14332. </varlistentry>
  14333. </variablelist>
  14334. <para>
  14335. <bridgehead renderas="sect4" id="numa_node_operator_less_bridgehead">
  14336. <phrase id="numa_node_operator_less"/>
  14337. <link linkend="numa_node_operator_less">Member
  14338. function <code>operator&lt;</code>()</link>
  14339. </bridgehead>
  14340. </para>
  14341. <programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">lhs</phrase><phrase role="special">,</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">rhs</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  14342. </programlisting>
  14343. <variablelist>
  14344. <title></title>
  14345. <varlistentry>
  14346. <term>Returns:</term>
  14347. <listitem>
  14348. <para>
  14349. <code><phrase role="keyword">true</phrase></code> if <code><phrase role="identifier">lhs</phrase>
  14350. <phrase role="special">!=</phrase> <phrase role="identifier">rhs</phrase></code>
  14351. is true and the implementation-defined total order of <code><phrase role="identifier">node</phrase><phrase
  14352. role="special">::</phrase><phrase role="identifier">id</phrase></code>
  14353. values places <code><phrase role="identifier">lhs</phrase></code> before
  14354. <code><phrase role="identifier">rhs</phrase></code>, false otherwise.
  14355. </para>
  14356. </listitem>
  14357. </varlistentry>
  14358. <varlistentry>
  14359. <term>Throws:</term>
  14360. <listitem>
  14361. <para>
  14362. Nothing.
  14363. </para>
  14364. </listitem>
  14365. </varlistentry>
  14366. </variablelist>
  14367. <para>
  14368. <bridgehead renderas="sect4" id="numa_topology_bridgehead">
  14369. <phrase id="numa_topology"/>
  14370. <link linkend="numa_topology">Non-member function <code>numa::topology()</code></link>
  14371. </bridgehead>
  14372. </para>
  14373. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">topology</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  14374. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  14375. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  14376. <phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
  14377. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">topology</phrase><phrase role="special">();</phrase>
  14378. <phrase role="special">}}}</phrase>
  14379. </programlisting>
  14380. <variablelist>
  14381. <title></title>
  14382. <varlistentry>
  14383. <term>Effects:</term>
  14384. <listitem>
  14385. <para>
  14386. Evaluates the NUMA topology.
  14387. </para>
  14388. </listitem>
  14389. </varlistentry>
  14390. <varlistentry>
  14391. <term>Returns:</term>
  14392. <listitem>
  14393. <para>
  14394. a vector of NUMA-nodes describing the NUMA architecture of the system
  14395. (each element represents a NUMA-node).
  14396. </para>
  14397. </listitem>
  14398. </varlistentry>
  14399. <varlistentry>
  14400. <term>Throws:</term>
  14401. <listitem>
  14402. <para>
  14403. <code><phrase role="identifier">system_error</phrase></code>
  14404. </para>
  14405. </listitem>
  14406. </varlistentry>
  14407. </variablelist>
  14408. <para>
  14409. <bridgehead renderas="sect4" id="numa_pin_thread_bridgehead">
  14410. <phrase id="numa_pin_thread"/>
  14411. <link linkend="numa_pin_thread">Non-member function
  14412. <code>numa::pin_thread()</code></link>
  14413. </bridgehead>
  14414. </para>
  14415. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">pin_thread</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  14416. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  14417. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  14418. <phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
  14419. <phrase role="keyword">void</phrase> <phrase role="identifier">pin_thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">);</phrase>
  14420. <phrase role="keyword">void</phrase> <phrase role="identifier">pin_thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">native_handle_type</phrase> <phrase role="identifier">h</phrase><phrase role="special">);</phrase>
  14421. <phrase role="special">}}}</phrase>
  14422. </programlisting>
  14423. <variablelist>
  14424. <title></title>
  14425. <varlistentry>
  14426. <term>Effects:</term>
  14427. <listitem>
  14428. <para>
  14429. First version pins <code><phrase role="keyword">this</phrase> <phrase
  14430. role="identifier">thread</phrase></code> to the logical cpu with ID
  14431. <code><phrase role="identifier">cpu_id</phrase></code>, e.g. the operating
  14432. system scheduler will not migrate the thread to another logical cpu.
  14433. The second variant pins the thread with the native ID <code><phrase role="identifier">h</phrase></code>
  14434. to logical cpu with ID <code><phrase role="identifier">cpu_id</phrase></code>.
  14435. </para>
  14436. </listitem>
  14437. </varlistentry>
  14438. <varlistentry>
  14439. <term>Throws:</term>
  14440. <listitem>
  14441. <para>
  14442. <code><phrase role="identifier">system_error</phrase></code>
  14443. </para>
  14444. </listitem>
  14445. </varlistentry>
  14446. </variablelist>
  14447. <para>
  14448. <bridgehead renderas="sect4" id="class_numa_work_stealing_bridgehead">
  14449. <phrase id="class_numa_work_stealing"/>
  14450. <link linkend="class_numa_work_stealing">Class
  14451. <code>numa::work_stealing</code></link>
  14452. </bridgehead>
  14453. </para>
  14454. <para>
  14455. This class implements <link linkend="class_algorithm"><code>algorithm</code></link>; the thread running this scheduler
  14456. is pinned to the given logical cpu. If the local ready-queue runs out of ready
  14457. fibers, ready fibers are stolen from other schedulers that run on logical cpus
  14458. that belong to the same NUMA-node (local memory access).<sbr/> If no ready
  14459. fibers can be stolen from the local NUMA-node, the algorithm selects schedulers
  14460. running on other NUMA-nodes (remote memory access).<sbr/> The victim scheduler
  14461. (from which a ready fiber is stolen) is selected at random.
  14462. </para>
  14463. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">algo</phrase><phrase role="special">/</phrase><phrase role="identifier">work_stealing</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  14464. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  14465. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  14466. <phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
  14467. <phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
  14468. <phrase role="keyword">class</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase>
  14469. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  14470. <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase>
  14471. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">node_id</phrase><phrase role="special">,</phrase>
  14472. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">topo</phrase><phrase role="special">,</phrase>
  14473. <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase>
  14474. <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  14475. <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  14476. <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  14477. <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
  14478. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  14479. <phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  14480. <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  14481. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  14482. <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  14483. <phrase role="special">};</phrase>
  14484. <phrase role="special">}}}}</phrase>
  14485. </programlisting>
  14486. <bridgehead renderas="sect3" id="fiber.numa.h2">
  14487. <phrase id="fiber.numa.constructor"/><link linkend="fiber.numa.constructor">Constructor</link>
  14488. </bridgehead>
  14489. <programlisting><phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">node_id</phrase><phrase role="special">,</phrase>
  14490. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">topo</phrase><phrase role="special">,</phrase>
  14491. <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase>
  14492. </programlisting>
  14493. <variablelist>
  14494. <title></title>
  14495. <varlistentry>
  14496. <term>Effects:</term>
  14497. <listitem>
  14498. <para>
  14499. Constructs work-stealing scheduling algorithm. The thread is pinned to
  14500. logical cpu with ID <code><phrase role="identifier">cpu_id</phrase></code>.
  14501. If local ready-queue runs out of ready fibers, ready fibers are stolen
  14502. from other schedulers using <code><phrase role="identifier">topology</phrase></code>
  14503. (represents the NUMA-topology of the system).
  14504. </para>
  14505. </listitem>
  14506. </varlistentry>
  14507. <varlistentry>
  14508. <term>Throws:</term>
  14509. <listitem>
  14510. <para>
  14511. <code><phrase role="identifier">system_error</phrase></code>
  14512. </para>
  14513. </listitem>
  14514. </varlistentry>
  14515. <varlistentry>
  14516. <term>Note:</term>
  14517. <listitem>
  14518. <para>
  14519. If <code><phrase role="identifier">suspend</phrase></code> is set to
  14520. <code><phrase role="keyword">true</phrase></code>, then the scheduler
  14521. suspends if no ready fiber could be stolen. The scheduler will by woken
  14522. up if a sleeping fiber times out or it was notified from remote (other
  14523. thread or fiber scheduler).
  14524. </para>
  14525. </listitem>
  14526. </varlistentry>
  14527. </variablelist>
  14528. <para>
  14529. <bridgehead renderas="sect4" id="numa_work_stealing_awakened_bridgehead">
  14530. <phrase id="numa_work_stealing_awakened"/>
  14531. <link linkend="numa_work_stealing_awakened">Member
  14532. function <code>awakened</code>()</link>
  14533. </bridgehead>
  14534. </para>
  14535. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  14536. </programlisting>
  14537. <variablelist>
  14538. <title></title>
  14539. <varlistentry>
  14540. <term>Effects:</term>
  14541. <listitem>
  14542. <para>
  14543. Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto
  14544. the shared ready queue.
  14545. </para>
  14546. </listitem>
  14547. </varlistentry>
  14548. <varlistentry>
  14549. <term>Throws:</term>
  14550. <listitem>
  14551. <para>
  14552. Nothing.
  14553. </para>
  14554. </listitem>
  14555. </varlistentry>
  14556. </variablelist>
  14557. <para>
  14558. <bridgehead renderas="sect4" id="numa_work_stealing_pick_next_bridgehead">
  14559. <phrase id="numa_work_stealing_pick_next"/>
  14560. <link linkend="numa_work_stealing_pick_next">Member
  14561. function <code>pick_next</code>()</link>
  14562. </bridgehead>
  14563. </para>
  14564. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  14565. </programlisting>
  14566. <variablelist>
  14567. <title></title>
  14568. <varlistentry>
  14569. <term>Returns:</term>
  14570. <listitem>
  14571. <para>
  14572. the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code>
  14573. if the queue is empty.
  14574. </para>
  14575. </listitem>
  14576. </varlistentry>
  14577. <varlistentry>
  14578. <term>Throws:</term>
  14579. <listitem>
  14580. <para>
  14581. Nothing.
  14582. </para>
  14583. </listitem>
  14584. </varlistentry>
  14585. <varlistentry>
  14586. <term>Note:</term>
  14587. <listitem>
  14588. <para>
  14589. Placing ready fibers onto the tail of the sahred queue, and returning
  14590. them from the head of that queue, shares the thread between ready fibers
  14591. in round-robin fashion.
  14592. </para>
  14593. </listitem>
  14594. </varlistentry>
  14595. </variablelist>
  14596. <para>
  14597. <bridgehead renderas="sect4" id="numa_work_stealing_has_ready_fibers_bridgehead">
  14598. <phrase id="numa_work_stealing_has_ready_fibers"/>
  14599. <link linkend="numa_work_stealing_has_ready_fibers">Member
  14600. function <code>has_ready_fibers</code>()</link>
  14601. </bridgehead>
  14602. </para>
  14603. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  14604. </programlisting>
  14605. <variablelist>
  14606. <title></title>
  14607. <varlistentry>
  14608. <term>Returns:</term>
  14609. <listitem>
  14610. <para>
  14611. <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
  14612. ready to run.
  14613. </para>
  14614. </listitem>
  14615. </varlistentry>
  14616. <varlistentry>
  14617. <term>Throws:</term>
  14618. <listitem>
  14619. <para>
  14620. Nothing.
  14621. </para>
  14622. </listitem>
  14623. </varlistentry>
  14624. </variablelist>
  14625. <para>
  14626. <bridgehead renderas="sect4" id="numa_work_stealing_suspend_until_bridgehead">
  14627. <phrase id="numa_work_stealing_suspend_until"/>
  14628. <link linkend="numa_work_stealing_suspend_until">Member
  14629. function <code>suspend_until</code>()</link>
  14630. </bridgehead>
  14631. </para>
  14632. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
  14633. </programlisting>
  14634. <variablelist>
  14635. <title></title>
  14636. <varlistentry>
  14637. <term>Effects:</term>
  14638. <listitem>
  14639. <para>
  14640. Informs <code><phrase role="identifier">work_stealing</phrase></code>
  14641. that no ready fiber will be available until time-point <code><phrase
  14642. role="identifier">abs_time</phrase></code>. This implementation blocks
  14643. in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
  14644. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  14645. role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
  14646. role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
  14647. </para>
  14648. </listitem>
  14649. </varlistentry>
  14650. <varlistentry>
  14651. <term>Throws:</term>
  14652. <listitem>
  14653. <para>
  14654. Nothing.
  14655. </para>
  14656. </listitem>
  14657. </varlistentry>
  14658. </variablelist>
  14659. <para>
  14660. <bridgehead renderas="sect4" id="numa_work_stealing_notify_bridgehead">
  14661. <phrase id="numa_work_stealing_notify"/>
  14662. <link linkend="numa_work_stealing_notify">Member
  14663. function <code>notify</code>()</link>
  14664. </bridgehead>
  14665. </para>
  14666. <programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
  14667. </programlisting>
  14668. <variablelist>
  14669. <title></title>
  14670. <varlistentry>
  14671. <term>Effects:</term>
  14672. <listitem>
  14673. <para>
  14674. Wake up a pending call to <link linkend="work_stealing_suspend_until"><code>work_stealing::suspend_until()</code></link>,
  14675. some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
  14676. role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
  14677. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  14678. role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
  14679. role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
  14680. </para>
  14681. </listitem>
  14682. </varlistentry>
  14683. <varlistentry>
  14684. <term>Throws:</term>
  14685. <listitem>
  14686. <para>
  14687. Nothing.
  14688. </para>
  14689. </listitem>
  14690. </varlistentry>
  14691. </variablelist>
  14692. </section>
  14693. <section id="fiber.gpu_computing">
  14694. <title><link linkend="fiber.gpu_computing">GPU computing</link></title>
  14695. <section id="fiber.gpu_computing.cuda">
  14696. <title><anchor id="cuda"/><link linkend="fiber.gpu_computing.cuda">CUDA</link></title>
  14697. <para>
  14698. <ulink url="http://developer.nvidia.com/cuda-zone/">CUDA (Compute Unified
  14699. Device Architecture)</ulink> is a platform for parallel computing on NVIDIA
  14700. GPUs. The application programming interface of CUDA gives access to GPU's
  14701. instruction set and computation resources (Execution of compute kernels).
  14702. </para>
  14703. <bridgehead renderas="sect4" id="fiber.gpu_computing.cuda.h0">
  14704. <phrase id="fiber.gpu_computing.cuda.synchronization_with_cuda_streams"/><link
  14705. linkend="fiber.gpu_computing.cuda.synchronization_with_cuda_streams">Synchronization
  14706. with CUDA streams</link>
  14707. </bridgehead>
  14708. <para>
  14709. CUDA operation such as compute kernels or memory transfer (between host and
  14710. device) can be grouped/queued by CUDA streams. are executed on the GPUs.
  14711. Boost.Fiber enables a fiber to sleep (suspend) till a CUDA stream has completed
  14712. its operations. This enables applications to run other fibers on the CPU
  14713. without the need to spawn an additional OS-threads. And resume the fiber
  14714. when the CUDA streams has finished.
  14715. </para>
  14716. <programlisting><phrase role="identifier">__global__</phrase>
  14717. <phrase role="keyword">void</phrase> <phrase role="identifier">kernel</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">a</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">b</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">c</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14718. <phrase role="keyword">int</phrase> <phrase role="identifier">idx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">threadIdx</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase> <phrase role="special">+</phrase> <phrase role="identifier">blockIdx</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase> <phrase role="special">*</phrase> <phrase role="identifier">blockDim</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase><phrase role="special">;</phrase>
  14719. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">idx</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">size</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14720. <phrase role="keyword">int</phrase> <phrase role="identifier">idx1</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">idx</phrase> <phrase role="special">+</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">%</phrase> <phrase role="number">256</phrase><phrase role="special">;</phrase>
  14721. <phrase role="keyword">int</phrase> <phrase role="identifier">idx2</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">idx</phrase> <phrase role="special">+</phrase> <phrase role="number">2</phrase><phrase role="special">)</phrase> <phrase role="special">%</phrase> <phrase role="number">256</phrase><phrase role="special">;</phrase>
  14722. <phrase role="keyword">float</phrase> <phrase role="identifier">as</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx1</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx2</phrase><phrase role="special">])</phrase> <phrase role="special">/</phrase> <phrase role="number">3.0f</phrase><phrase role="special">;</phrase>
  14723. <phrase role="keyword">float</phrase> <phrase role="identifier">bs</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx1</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx2</phrase><phrase role="special">])</phrase> <phrase role="special">/</phrase> <phrase role="number">3.0f</phrase><phrase role="special">;</phrase>
  14724. <phrase role="identifier">c</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">as</phrase> <phrase role="special">+</phrase> <phrase role="identifier">bs</phrase><phrase role="special">)</phrase> <phrase role="special">/</phrase> <phrase role="number">2</phrase><phrase role="special">;</phrase>
  14725. <phrase role="special">}</phrase>
  14726. <phrase role="special">}</phrase>
  14727. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">([&amp;</phrase><phrase role="identifier">done</phrase><phrase role="special">]{</phrase>
  14728. <phrase role="identifier">cudaStream_t</phrase> <phrase role="identifier">stream</phrase><phrase role="special">;</phrase>
  14729. <phrase role="identifier">cudaStreamCreate</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
  14730. <phrase role="keyword">int</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="number">1024</phrase> <phrase role="special">*</phrase> <phrase role="number">1024</phrase><phrase role="special">;</phrase>
  14731. <phrase role="keyword">int</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">=</phrase> <phrase role="number">20</phrase> <phrase role="special">*</phrase> <phrase role="identifier">size</phrase><phrase role="special">;</phrase>
  14732. <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">;</phrase>
  14733. <phrase role="identifier">cudaHostAlloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaHostAllocDefault</phrase><phrase role="special">);</phrase>
  14734. <phrase role="identifier">cudaHostAlloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaHostAllocDefault</phrase><phrase role="special">);</phrase>
  14735. <phrase role="identifier">cudaHostAlloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaHostAllocDefault</phrase><phrase role="special">);</phrase>
  14736. <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">;</phrase>
  14737. <phrase role="identifier">cudaMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  14738. <phrase role="identifier">cudaMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  14739. <phrase role="identifier">cudaMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  14740. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">minstd_rand</phrase> <phrase role="identifier">generator</phrase><phrase role="special">;</phrase>
  14741. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int_distribution</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase>
  14742. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">full_size</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14743. <phrase role="identifier">host_a</phrase><phrase role="special">[</phrase><phrase role="identifier">i</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase> <phrase role="identifier">generator</phrase><phrase role="special">);</phrase>
  14744. <phrase role="identifier">host_b</phrase><phrase role="special">[</phrase><phrase role="identifier">i</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase> <phrase role="identifier">generator</phrase><phrase role="special">);</phrase>
  14745. <phrase role="special">}</phrase>
  14746. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">full_size</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">+=</phrase> <phrase role="identifier">size</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14747. <phrase role="identifier">cudaMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">host_a</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaMemcpyHostToDevice</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
  14748. <phrase role="identifier">cudaMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">host_b</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaMemcpyHostToDevice</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
  14749. <phrase role="identifier">kernel</phrase><phrase role="special">&lt;&lt;&lt;</phrase> <phrase role="identifier">size</phrase> <phrase role="special">/</phrase> <phrase role="number">256</phrase><phrase role="special">,</phrase> <phrase role="number">256</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase> <phrase role="special">&gt;&gt;&gt;(</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase>
  14750. <phrase role="identifier">cudaMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaMemcpyDeviceToHost</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
  14751. <phrase role="special">}</phrase>
  14752. <phrase role="keyword">auto</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">cuda</phrase><phrase role="special">::</phrase><phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> <phrase role="comment">// suspend fiber till CUDA stream has finished</phrase>
  14753. <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase> <phrase role="special">==</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">&lt;</phrase> <phrase role="number">0</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  14754. <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaSuccess</phrase> <phrase role="special">==</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">&lt;</phrase> <phrase role="number">1</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  14755. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;f1: GPU computation finished&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  14756. <phrase role="identifier">cudaFreeHost</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">);</phrase>
  14757. <phrase role="identifier">cudaFreeHost</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">);</phrase>
  14758. <phrase role="identifier">cudaFreeHost</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">);</phrase>
  14759. <phrase role="identifier">cudaFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">);</phrase>
  14760. <phrase role="identifier">cudaFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">);</phrase>
  14761. <phrase role="identifier">cudaFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase>
  14762. <phrase role="identifier">cudaStreamDestroy</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
  14763. <phrase role="special">});</phrase>
  14764. <phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  14765. </programlisting>
  14766. <bridgehead renderas="sect4" id="fiber.gpu_computing.cuda.h1">
  14767. <phrase id="fiber.gpu_computing.cuda.synopsis"/><link linkend="fiber.gpu_computing.cuda.synopsis">Synopsis</link>
  14768. </bridgehead>
  14769. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">cuda</phrase><phrase role="special">/</phrase><phrase role="identifier">waitfor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  14770. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  14771. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  14772. <phrase role="keyword">namespace</phrase> <phrase role="identifier">cuda</phrase> <phrase role="special">{</phrase>
  14773. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">cudaStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">cudaError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaStream_t</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase>
  14774. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">cudaStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">cudaError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaStream_t</phrase> <phrase role="special">...</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase>
  14775. <phrase role="special">}}}</phrase>
  14776. </programlisting>
  14777. <para>
  14778. <bridgehead renderas="sect4" id="cuda_waitfor_bridgehead">
  14779. <phrase id="cuda_waitfor"/>
  14780. <link linkend="cuda_waitfor">Non-member function <code>cuda::waitfor()</code></link>
  14781. </bridgehead>
  14782. </para>
  14783. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">cuda</phrase><phrase role="special">/</phrase><phrase role="identifier">waitfor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  14784. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  14785. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  14786. <phrase role="keyword">namespace</phrase> <phrase role="identifier">cuda</phrase> <phrase role="special">{</phrase>
  14787. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">cudaStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">cudaError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaStream_t</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase>
  14788. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">cudaStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">cudaError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaStream_t</phrase> <phrase role="special">...</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase>
  14789. <phrase role="special">}}}</phrase>
  14790. </programlisting>
  14791. <variablelist>
  14792. <title></title>
  14793. <varlistentry>
  14794. <term>Effects:</term>
  14795. <listitem>
  14796. <para>
  14797. Suspends active fiber till CUDA stream has finished its operations.
  14798. </para>
  14799. </listitem>
  14800. </varlistentry>
  14801. <varlistentry>
  14802. <term>Returns:</term>
  14803. <listitem>
  14804. <para>
  14805. tuple of stream reference and the CUDA stream status
  14806. </para>
  14807. </listitem>
  14808. </varlistentry>
  14809. </variablelist>
  14810. </section>
  14811. <section id="fiber.gpu_computing.hip">
  14812. <title><anchor id="hip"/><link linkend="fiber.gpu_computing.hip">ROCm/HIP</link></title>
  14813. <para>
  14814. <ulink url="http://github.com/ROCm-Developer-Tools/HIP/tree/roc-1.6.0/">HIP</ulink>
  14815. is part of the <ulink url="http://rocm.github.io/">ROC (Radeon Open Compute)</ulink>
  14816. platform for parallel computing on AMD and NVIDIA GPUs. The application programming
  14817. interface of HIP gives access to GPU's instruction set and computation resources
  14818. (Execution of compute kernels).
  14819. </para>
  14820. <bridgehead renderas="sect4" id="fiber.gpu_computing.hip.h0">
  14821. <phrase id="fiber.gpu_computing.hip.synchronization_with_rocm_hip_streams"/><link
  14822. linkend="fiber.gpu_computing.hip.synchronization_with_rocm_hip_streams">Synchronization
  14823. with ROCm/HIP streams</link>
  14824. </bridgehead>
  14825. <para>
  14826. HIP operation such as compute kernels or memory transfer (between host and
  14827. device) can be grouped/queued by HIP streams. are executed on the GPUs. Boost.Fiber
  14828. enables a fiber to sleep (suspend) till a HIP stream has completed its operations.
  14829. This enables applications to run other fibers on the CPU without the need
  14830. to spawn an additional OS-threads. And resume the fiber when the HIP streams
  14831. has finished.
  14832. </para>
  14833. <programlisting><phrase role="identifier">__global__</phrase>
  14834. <phrase role="keyword">void</phrase> <phrase role="identifier">kernel</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">a</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">b</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">c</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14835. <phrase role="keyword">int</phrase> <phrase role="identifier">idx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">threadIdx</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase> <phrase role="special">+</phrase> <phrase role="identifier">blockIdx</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase> <phrase role="special">*</phrase> <phrase role="identifier">blockDim</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase><phrase role="special">;</phrase>
  14836. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">idx</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">size</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14837. <phrase role="keyword">int</phrase> <phrase role="identifier">idx1</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">idx</phrase> <phrase role="special">+</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">%</phrase> <phrase role="number">256</phrase><phrase role="special">;</phrase>
  14838. <phrase role="keyword">int</phrase> <phrase role="identifier">idx2</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">idx</phrase> <phrase role="special">+</phrase> <phrase role="number">2</phrase><phrase role="special">)</phrase> <phrase role="special">%</phrase> <phrase role="number">256</phrase><phrase role="special">;</phrase>
  14839. <phrase role="keyword">float</phrase> <phrase role="identifier">as</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx1</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx2</phrase><phrase role="special">])</phrase> <phrase role="special">/</phrase> <phrase role="number">3.0f</phrase><phrase role="special">;</phrase>
  14840. <phrase role="keyword">float</phrase> <phrase role="identifier">bs</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx1</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx2</phrase><phrase role="special">])</phrase> <phrase role="special">/</phrase> <phrase role="number">3.0f</phrase><phrase role="special">;</phrase>
  14841. <phrase role="identifier">c</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">as</phrase> <phrase role="special">+</phrase> <phrase role="identifier">bs</phrase><phrase role="special">)</phrase> <phrase role="special">/</phrase> <phrase role="number">2</phrase><phrase role="special">;</phrase>
  14842. <phrase role="special">}</phrase>
  14843. <phrase role="special">}</phrase>
  14844. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">([&amp;</phrase><phrase role="identifier">done</phrase><phrase role="special">]{</phrase>
  14845. <phrase role="identifier">hipStream_t</phrase> <phrase role="identifier">stream</phrase><phrase role="special">;</phrase>
  14846. <phrase role="identifier">hipStreamCreate</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
  14847. <phrase role="keyword">int</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="number">1024</phrase> <phrase role="special">*</phrase> <phrase role="number">1024</phrase><phrase role="special">;</phrase>
  14848. <phrase role="keyword">int</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">=</phrase> <phrase role="number">20</phrase> <phrase role="special">*</phrase> <phrase role="identifier">size</phrase><phrase role="special">;</phrase>
  14849. <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">;</phrase>
  14850. <phrase role="identifier">hipHostMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipHostMallocDefault</phrase><phrase role="special">);</phrase>
  14851. <phrase role="identifier">hipHostMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipHostMallocDefault</phrase><phrase role="special">);</phrase>
  14852. <phrase role="identifier">hipHostMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipHostMallocDefault</phrase><phrase role="special">);</phrase>
  14853. <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">;</phrase>
  14854. <phrase role="identifier">hipMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  14855. <phrase role="identifier">hipMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  14856. <phrase role="identifier">hipMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  14857. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">minstd_rand</phrase> <phrase role="identifier">generator</phrase><phrase role="special">;</phrase>
  14858. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int_distribution</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase>
  14859. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">full_size</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14860. <phrase role="identifier">host_a</phrase><phrase role="special">[</phrase><phrase role="identifier">i</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase> <phrase role="identifier">generator</phrase><phrase role="special">);</phrase>
  14861. <phrase role="identifier">host_b</phrase><phrase role="special">[</phrase><phrase role="identifier">i</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase> <phrase role="identifier">generator</phrase><phrase role="special">);</phrase>
  14862. <phrase role="special">}</phrase>
  14863. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">full_size</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">+=</phrase> <phrase role="identifier">size</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14864. <phrase role="identifier">hipMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">host_a</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipMemcpyHostToDevice</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
  14865. <phrase role="identifier">hipMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">host_b</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipMemcpyHostToDevice</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
  14866. <phrase role="identifier">hipLaunchKernel</phrase><phrase role="special">(</phrase><phrase role="identifier">kernel</phrase><phrase role="special">,</phrase> <phrase role="identifier">dim3</phrase><phrase role="special">(</phrase><phrase role="identifier">size</phrase> <phrase role="special">/</phrase> <phrase role="number">256</phrase><phrase role="special">),</phrase> <phrase role="identifier">dim3</phrase><phrase role="special">(</phrase><phrase role="number">256</phrase><phrase role="special">),</phrase> <phrase role="number">0</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase>
  14867. <phrase role="identifier">hipMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipMemcpyDeviceToHost</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
  14868. <phrase role="special">}</phrase>
  14869. <phrase role="keyword">auto</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">hip</phrase><phrase role="special">::</phrase><phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> <phrase role="comment">// suspend fiber till HIP stream has finished</phrase>
  14870. <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase> <phrase role="special">==</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">&lt;</phrase> <phrase role="number">0</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  14871. <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipSuccess</phrase> <phrase role="special">==</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">&lt;</phrase> <phrase role="number">1</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
  14872. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;f1: GPU computation finished&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
  14873. <phrase role="identifier">hipHostFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">);</phrase>
  14874. <phrase role="identifier">hipHostFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">);</phrase>
  14875. <phrase role="identifier">hipHostFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">);</phrase>
  14876. <phrase role="identifier">hipFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">);</phrase>
  14877. <phrase role="identifier">hipFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">);</phrase>
  14878. <phrase role="identifier">hipFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase>
  14879. <phrase role="identifier">hipStreamDestroy</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
  14880. <phrase role="special">});</phrase>
  14881. <phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  14882. </programlisting>
  14883. <bridgehead renderas="sect4" id="fiber.gpu_computing.hip.h1">
  14884. <phrase id="fiber.gpu_computing.hip.synopsis"/><link linkend="fiber.gpu_computing.hip.synopsis">Synopsis</link>
  14885. </bridgehead>
  14886. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">hip</phrase><phrase role="special">/</phrase><phrase role="identifier">waitfor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  14887. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  14888. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  14889. <phrase role="keyword">namespace</phrase> <phrase role="identifier">hip</phrase> <phrase role="special">{</phrase>
  14890. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">hipStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">hipError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipStream_t</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase>
  14891. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">hipStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">hipError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipStream_t</phrase> <phrase role="special">...</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase>
  14892. <phrase role="special">}}}</phrase>
  14893. </programlisting>
  14894. <para>
  14895. <bridgehead renderas="sect4" id="hip_waitfor_bridgehead">
  14896. <phrase id="hip_waitfor"/>
  14897. <link linkend="hip_waitfor">Non-member function <code>hip::waitfor()</code></link>
  14898. </bridgehead>
  14899. </para>
  14900. <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">hip</phrase><phrase role="special">/</phrase><phrase role="identifier">waitfor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
  14901. <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
  14902. <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
  14903. <phrase role="keyword">namespace</phrase> <phrase role="identifier">hip</phrase> <phrase role="special">{</phrase>
  14904. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">hipStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">hipError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipStream_t</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase>
  14905. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">hipStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">hipError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipStream_t</phrase> <phrase role="special">...</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase>
  14906. <phrase role="special">}}}</phrase>
  14907. </programlisting>
  14908. <variablelist>
  14909. <title></title>
  14910. <varlistentry>
  14911. <term>Effects:</term>
  14912. <listitem>
  14913. <para>
  14914. Suspends active fiber till HIP stream has finished its operations.
  14915. </para>
  14916. </listitem>
  14917. </varlistentry>
  14918. <varlistentry>
  14919. <term>Returns:</term>
  14920. <listitem>
  14921. <para>
  14922. tuple of stream reference and the HIP stream status
  14923. </para>
  14924. </listitem>
  14925. </varlistentry>
  14926. </variablelist>
  14927. </section>
  14928. </section>
  14929. <section id="fiber.worker">
  14930. <title><anchor id="worker"/><link linkend="fiber.worker">Running with worker
  14931. threads</link></title>
  14932. <bridgehead renderas="sect3" id="fiber.worker.h0">
  14933. <phrase id="fiber.worker.keep_workers_running"/><link linkend="fiber.worker.keep_workers_running">Keep
  14934. workers running</link>
  14935. </bridgehead>
  14936. <para>
  14937. If a worker thread is used but no fiber is created or parts of the framework
  14938. (like <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>) are touched, then no fiber scheduler
  14939. is instantiated.
  14940. </para>
  14941. <programlisting><phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase>
  14942. <phrase role="special">[]{</phrase>
  14943. <phrase role="comment">// fiber scheduler not instantiated</phrase>
  14944. <phrase role="special">});</phrase>
  14945. <phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  14946. </programlisting>
  14947. <para>
  14948. If <emphasis>use_scheduling_algorithm&lt;&gt;()</emphasis> is invoked, the
  14949. fiber scheduler is created. If the worker thread simply returns, destroys the
  14950. scheduler and terminates.
  14951. </para>
  14952. <programlisting><phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase>
  14953. <phrase role="special">[]{</phrase>
  14954. <phrase role="comment">// fiber scheduler created</phrase>
  14955. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_fiber_scheduler</phrase><phrase role="special">&gt;();</phrase>
  14956. <phrase role="special">});</phrase>
  14957. <phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  14958. </programlisting>
  14959. <para>
  14960. In order to keep the worker thread running, the fiber associated with the thread
  14961. stack (which is called <quote>main</quote> fiber) is blocked. For instance
  14962. the <quote>main</quote> fiber might wait on a <link linkend="class_condition_variable"><code>condition_variable</code></link>.
  14963. For a gracefully shutdown <link linkend="class_condition_variable"><code>condition_variable</code></link> is signalled
  14964. and the <quote>main</quote> fiber returns. The scheduler gets destructed if
  14965. all fibers of the worker thread have been terminated.
  14966. </para>
  14967. <programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">;</phrase>
  14968. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable_any</phrase> <phrase role="identifier">cv</phrase><phrase role="special">;</phrase>
  14969. <phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase>
  14970. <phrase role="special">[&amp;</phrase><phrase role="identifier">mtx</phrase><phrase role="special">,&amp;</phrase><phrase role="identifier">cv</phrase><phrase role="special">]{</phrase>
  14971. <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
  14972. <phrase role="comment">// suspend till signalled</phrase>
  14973. <phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase><phrase role="identifier">mtx</phrase><phrase role="special">);</phrase>
  14974. <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
  14975. <phrase role="special">});</phrase>
  14976. <phrase role="comment">// signal termination</phrase>
  14977. <phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase>
  14978. <phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  14979. </programlisting>
  14980. <bridgehead renderas="sect3" id="fiber.worker.h1">
  14981. <phrase id="fiber.worker.processing_tasks"/><link linkend="fiber.worker.processing_tasks">Processing
  14982. tasks</link>
  14983. </bridgehead>
  14984. <para>
  14985. Tasks can be transferred via channels. The worker thread runs a pool of fibers
  14986. that dequeue and executed tasks from the channel. The termination is signalled
  14987. via closing the channel.
  14988. </para>
  14989. <programlisting><phrase role="keyword">using</phrase> <phrase role="identifier">task</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">function</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">()&gt;;</phrase>
  14990. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">task</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">ch</phrase><phrase role="special">{</phrase><phrase role="number">1024</phrase><phrase role="special">};</phrase>
  14991. <phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase>
  14992. <phrase role="special">[&amp;</phrase><phrase role="identifier">ch</phrase><phrase role="special">]{</phrase>
  14993. <phrase role="comment">// create pool of fibers</phrase>
  14994. <phrase role="keyword">for</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">=</phrase><phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase><phrase role="special">&lt;</phrase><phrase role="number">10</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  14995. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">{</phrase>
  14996. <phrase role="special">[&amp;</phrase><phrase role="identifier">ch</phrase><phrase role="special">]{</phrase>
  14997. <phrase role="identifier">task</phrase> <phrase role="identifier">tsk</phrase><phrase role="special">;</phrase>
  14998. <phrase role="comment">// dequeue and process tasks</phrase>
  14999. <phrase role="keyword">while</phrase> <phrase role="special">(</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">closed</phrase><phrase role="special">!=</phrase><phrase role="identifier">ch</phrase><phrase role="special">.</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">tsk</phrase><phrase role="special">)){</phrase>
  15000. <phrase role="identifier">tsk</phrase><phrase role="special">();</phrase>
  15001. <phrase role="special">}</phrase>
  15002. <phrase role="special">}}.</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
  15003. <phrase role="special">}</phrase>
  15004. <phrase role="identifier">task</phrase> <phrase role="identifier">tsk</phrase><phrase role="special">;</phrase>
  15005. <phrase role="comment">// dequeue and process tasks</phrase>
  15006. <phrase role="keyword">while</phrase> <phrase role="special">(</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">closed</phrase><phrase role="special">!=</phrase><phrase role="identifier">ch</phrase><phrase role="special">.</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">tsk</phrase><phrase role="special">)){</phrase>
  15007. <phrase role="identifier">tsk</phrase><phrase role="special">();</phrase>
  15008. <phrase role="special">}</phrase>
  15009. <phrase role="special">});</phrase>
  15010. <phrase role="comment">// feed channel with tasks</phrase>
  15011. <phrase role="identifier">ch</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">([]{</phrase> <phrase role="special">...</phrase> <phrase role="special">});</phrase>
  15012. <phrase role="special">...</phrase>
  15013. <phrase role="comment">// signal termination</phrase>
  15014. <phrase role="identifier">ch</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
  15015. <phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  15016. </programlisting>
  15017. <para>
  15018. An alternative is to use a work-stealing scheduler. This kind of scheduling
  15019. algorithm a worker thread steals fibers from the ready-queue of other worker
  15020. threads if its own ready-queue is empty.
  15021. </para>
  15022. <note>
  15023. <para>
  15024. Wait till all worker threads have registered the work-stealing scheduling
  15025. algorithm.
  15026. </para>
  15027. </note>
  15028. <programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">;</phrase>
  15029. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable_any</phrase> <phrase role="identifier">cv</phrase><phrase role="special">;</phrase>
  15030. <phrase role="comment">// start wotrker-thread first</phrase>
  15031. <phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase>
  15032. <phrase role="special">[&amp;</phrase><phrase role="identifier">mtx</phrase><phrase role="special">,&amp;</phrase><phrase role="identifier">cv</phrase><phrase role="special">]{</phrase>
  15033. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase><phrase role="special">&gt;(</phrase><phrase role="number">2</phrase><phrase role="special">);</phrase>
  15034. <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
  15035. <phrase role="comment">// suspend main-fiber from the worker thread</phrase>
  15036. <phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase><phrase role="identifier">mtx</phrase><phrase role="special">);</phrase>
  15037. <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
  15038. <phrase role="special">});</phrase>
  15039. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase><phrase role="special">&gt;(</phrase><phrase role="number">2</phrase><phrase role="special">);</phrase>
  15040. <phrase role="comment">// create fibers with tasks</phrase>
  15041. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">{[]{</phrase> <phrase role="special">...</phrase> <phrase role="special">}};</phrase>
  15042. <phrase role="special">...</phrase>
  15043. <phrase role="comment">// signal termination</phrase>
  15044. <phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase>
  15045. <phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
  15046. </programlisting>
  15047. <important>
  15048. <para>
  15049. Because the TIB (thread information block on Windows) is not fully described
  15050. in the MSDN, it might be possible that not all required TIB-parts are swapped.
  15051. Using WinFiber implementation might be an alternative (see documentation
  15052. about <ulink url="http://www.boost.org/doc/libs/1_65_1/libs/context/doc/html/context/cc/implementations__fcontext_t__ucontext_t_and_winfiber.html"><emphasis>implementations
  15053. fcontext_t, ucontext_t and WinFiber of boost.context</emphasis></ulink>).
  15054. </para>
  15055. </important>
  15056. </section>
  15057. <section id="fiber.performance">
  15058. <title><link linkend="fiber.performance">Performance</link></title>
  15059. <para>
  15060. Performance measurements were taken using <code><phrase role="identifier">std</phrase><phrase
  15061. role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase
  15062. role="special">::</phrase><phrase role="identifier">highresolution_clock</phrase></code>,
  15063. with overhead corrections. The code was compiled with gcc-6.3.1, using build
  15064. options: variant = release, optimization = speed. Tests were executed on dual
  15065. Intel XEON E5 2620v4 2.2GHz, 16C/32T, 64GB RAM, running Linux (x86_64).
  15066. </para>
  15067. <para>
  15068. Measurements headed 1C/1T were run in a single-threaded process.
  15069. </para>
  15070. <para>
  15071. The <ulink url="https://github.com/atemerev/skynet">microbenchmark <emphasis>syknet</emphasis></ulink>
  15072. from Alexander Temerev was ported and used for performance measurements. At
  15073. the root the test spawns 10 threads-of-execution (ToE), e.g. actor/goroutine/fiber
  15074. etc.. Each spawned ToE spawns additional 10 ToEs ... until <emphasis role="bold">1,000,000</emphasis>
  15075. ToEs are created. ToEs return back their ordinal numbers (0 ... 999,999), which
  15076. are summed on the previous level and sent back upstream, until reaching the
  15077. root. The test was run 10-20 times, producing a range of values for each measurement.
  15078. </para>
  15079. <table frame="all" id="fiber.performance.time_per_actor_erlang_process_goroutine__other_languages___average_over_1_000_000_">
  15080. <title>time per actor/erlang process/goroutine (other languages) (average over
  15081. 1,000,000)</title>
  15082. <tgroup cols="3">
  15083. <thead>
  15084. <row>
  15085. <entry>
  15086. <para>
  15087. Haskell | stack-1.4.0/ghc-8.0.1
  15088. </para>
  15089. </entry>
  15090. <entry>
  15091. <para>
  15092. Go | go1.8.1
  15093. </para>
  15094. </entry>
  15095. <entry>
  15096. <para>
  15097. Erlang | erts-8.3
  15098. </para>
  15099. </entry>
  15100. </row>
  15101. </thead>
  15102. <tbody>
  15103. <row>
  15104. <entry>
  15105. <para>
  15106. 0.05 &#xb5;s - 0.06 &#xb5;s
  15107. </para>
  15108. </entry>
  15109. <entry>
  15110. <para>
  15111. 0.42 &#xb5;s - 0.49 &#xb5;s
  15112. </para>
  15113. </entry>
  15114. <entry>
  15115. <para>
  15116. 0.63 &#xb5;s - 0.73 &#xb5;s
  15117. </para>
  15118. </entry>
  15119. </row>
  15120. </tbody>
  15121. </tgroup>
  15122. </table>
  15123. <para>
  15124. Pthreads are created with a stack size of 8kB while <code><phrase role="identifier">std</phrase><phrase
  15125. role="special">::</phrase><phrase role="identifier">thread</phrase></code>'s
  15126. use the system default (1MB - 2MB). The microbenchmark could <emphasis role="bold">not</emphasis>
  15127. be <emphasis role="bold">run</emphasis> with 1,000,000 threads because of
  15128. <emphasis role="bold">resource exhaustion</emphasis> (pthread and std::thread).
  15129. Instead the test runs only at <emphasis role="bold">10,000</emphasis> threads.
  15130. </para>
  15131. <table frame="all" id="fiber.performance.time_per_thread__average_over_10_000___unable_to_spawn_1_000_000_threads_">
  15132. <title>time per thread (average over 10,000 - unable to spawn 1,000,000 threads)</title>
  15133. <tgroup cols="3">
  15134. <thead>
  15135. <row>
  15136. <entry>
  15137. <para>
  15138. pthread
  15139. </para>
  15140. </entry>
  15141. <entry>
  15142. <para>
  15143. <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  15144. role="identifier">thread</phrase></code>
  15145. </para>
  15146. </entry>
  15147. <entry>
  15148. <para>
  15149. <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  15150. role="identifier">async</phrase></code>
  15151. </para>
  15152. </entry>
  15153. </row>
  15154. </thead>
  15155. <tbody>
  15156. <row>
  15157. <entry>
  15158. <para>
  15159. 54 &#xb5;s - 73 &#xb5;s
  15160. </para>
  15161. </entry>
  15162. <entry>
  15163. <para>
  15164. 52 &#xb5;s - 73 &#xb5;s
  15165. </para>
  15166. </entry>
  15167. <entry>
  15168. <para>
  15169. 106 &#xb5;s - 122 &#xb5;s
  15170. </para>
  15171. </entry>
  15172. </row>
  15173. </tbody>
  15174. </tgroup>
  15175. </table>
  15176. <para>
  15177. The test utilizes 16 cores with Symmetric MultiThreading enabled (32 logical
  15178. CPUs). The fiber stacks are allocated by <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link>.
  15179. </para>
  15180. <para>
  15181. As the benchmark shows, the memory allocation algorithm is significant for
  15182. performance in a multithreaded environment. The tests use glibc&#8217;s memory allocation
  15183. algorithm (based on ptmalloc2) as well as Google&#8217;s <ulink url="http://goog-perftools.sourceforge.net/doc/tcmalloc.html">TCmalloc</ulink>
  15184. (via linkflags=&quot;-ltcmalloc&quot;).<footnote id="fiber.performance.f0">
  15185. <para>
  15186. Tais B. Ferreira, Rivalino Matias, Autran Macedo, Lucio B. Araujo <quote>An
  15187. Experimental Study on Memory Allocators in Multicore and Multithreaded Applications</quote>,
  15188. PDCAT &#8217;11 Proceedings of the 2011 12th International Conference on Parallel
  15189. and Distributed Computing, Applications and Technologies, pages 92-98
  15190. </para>
  15191. </footnote>
  15192. </para>
  15193. <para>
  15194. In the <link linkend="class_work_stealing"><code>work_stealing</code></link> scheduling algorithm, each thread has
  15195. its own local queue. Fibers that are ready to run are pushed to and popped
  15196. from the local queue. If the queue runs out of ready fibers, fibers are stolen
  15197. from the local queues of other participating threads.
  15198. </para>
  15199. <table frame="all" id="fiber.performance.time_per_fiber__average_over_1_000_000_">
  15200. <title>time per fiber (average over 1.000.000)</title>
  15201. <tgroup cols="2">
  15202. <thead>
  15203. <row>
  15204. <entry>
  15205. <para>
  15206. fiber (16C/32T, work stealing, tcmalloc)
  15207. </para>
  15208. </entry>
  15209. <entry>
  15210. <para>
  15211. fiber (1C/1T, round robin, tcmalloc)
  15212. </para>
  15213. </entry>
  15214. </row>
  15215. </thead>
  15216. <tbody>
  15217. <row>
  15218. <entry>
  15219. <para>
  15220. 0.05 &#xb5;s - 0.09 &#xb5;s
  15221. </para>
  15222. </entry>
  15223. <entry>
  15224. <para>
  15225. 1.69 &#xb5;s - 1.79 &#xb5;s
  15226. </para>
  15227. </entry>
  15228. </row>
  15229. </tbody>
  15230. </tgroup>
  15231. </table>
  15232. </section>
  15233. <section id="fiber.tuning">
  15234. <title><anchor id="tuning"/><link linkend="fiber.tuning">Tuning</link></title>
  15235. <bridgehead renderas="sect3" id="fiber.tuning.h0">
  15236. <phrase id="fiber.tuning.disable_synchronization"/><link linkend="fiber.tuning.disable_synchronization">Disable
  15237. synchronization</link>
  15238. </bridgehead>
  15239. <para>
  15240. With <link linkend="cross_thread_sync"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></link>
  15241. defined at the compiler&#8217;s command line, synchronization between fibers (in different
  15242. threads) is disabled. This is acceptable if the application is single threaded
  15243. and/or fibers are not synchronized between threads.
  15244. </para>
  15245. <bridgehead renderas="sect3" id="fiber.tuning.h1">
  15246. <phrase id="fiber.tuning.memory_allocation"/><link linkend="fiber.tuning.memory_allocation">Memory
  15247. allocation</link>
  15248. </bridgehead>
  15249. <para>
  15250. Memory allocation algorithm is significant for performance in a multithreaded
  15251. environment, especially for <emphasis role="bold">Boost.Fiber</emphasis> where
  15252. fiber stacks are allocated on the heap. The default user-level memory allocator
  15253. (UMA) of glibc is ptmalloc2 but it can be replaced by another UMA that fit
  15254. better for the concret work-load For instance Google&#8217;s <ulink url="http://goog-perftools.sourceforge.net/doc/tcmalloc.html">TCmalloc</ulink>
  15255. enables a better performance at the <emphasis>skynet</emphasis> microbenchmark
  15256. than glibc&#8217;s default memory allocator.
  15257. </para>
  15258. <bridgehead renderas="sect3" id="fiber.tuning.h2">
  15259. <phrase id="fiber.tuning.scheduling_strategies"/><link linkend="fiber.tuning.scheduling_strategies">Scheduling
  15260. strategies</link>
  15261. </bridgehead>
  15262. <para>
  15263. The fibers in a thread are coordinated by a fiber manager. Fibers trade control
  15264. cooperatively, rather than preemptively. Depending on the work-load several
  15265. strategies of scheduling the fibers are possible <footnote id="fiber.tuning.f0">
  15266. <para>
  15267. 1024cores.net: <ulink url="http://www.1024cores.net/home/scalable-architecture/task-scheduling-strategies">Task
  15268. Scheduling Strategies</ulink>
  15269. </para>
  15270. </footnote> that can be implmented on behalf of <link linkend="class_algorithm"><code>algorithm</code></link>.
  15271. </para>
  15272. <itemizedlist>
  15273. <listitem>
  15274. <simpara>
  15275. work-stealing: ready fibers are hold in a local queue, when the fiber-scheduler's
  15276. local queue runs out of ready fibers, it randomly selects another fiber-scheduler
  15277. and tries to steal a ready fiber from the victim (implemented in <link linkend="class_work_stealing"><code>work_stealing</code></link> and
  15278. <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link>)
  15279. </simpara>
  15280. </listitem>
  15281. <listitem>
  15282. <simpara>
  15283. work-requesting: ready fibers are hold in a local queue, when the fiber-scheduler's
  15284. local queue runs out of ready fibers, it randomly selects another fiber-scheduler
  15285. and requests for a ready fibers, the victim fiber-scheduler sends a ready-fiber
  15286. back
  15287. </simpara>
  15288. </listitem>
  15289. <listitem>
  15290. <simpara>
  15291. work-sharing: ready fibers are hold in a global queue, fiber-scheduler
  15292. concurrently push and pop ready fibers to/from the global queue (implemented
  15293. in <link linkend="class_shared_work"><code>shared_work</code></link>)
  15294. </simpara>
  15295. </listitem>
  15296. <listitem>
  15297. <simpara>
  15298. work-distribution: fibers that became ready are proactivly distributed
  15299. to idle fiber-schedulers or fiber-schedulers with low load
  15300. </simpara>
  15301. </listitem>
  15302. <listitem>
  15303. <simpara>
  15304. work-balancing: a dedicated (helper) fiber-scheduler periodically collects
  15305. informations about all fiber-scheduler running in other threads and re-distributes
  15306. ready fibers among them
  15307. </simpara>
  15308. </listitem>
  15309. </itemizedlist>
  15310. <bridgehead renderas="sect3" id="fiber.tuning.h3">
  15311. <phrase id="fiber.tuning.ttas_locks"/><link linkend="fiber.tuning.ttas_locks">TTAS
  15312. locks</link>
  15313. </bridgehead>
  15314. <para>
  15315. Boost.Fiber uses internally spinlocks to protect critical regions if fibers
  15316. running on different threads interact. Spinlocks are implemented as TTAS (test-test-and-set)
  15317. locks, i.e. the spinlock tests the lock before calling an atomic exchange.
  15318. This strategy helps to reduce the cache line invalidations triggered by acquiring/releasing
  15319. the lock.
  15320. </para>
  15321. <bridgehead renderas="sect3" id="fiber.tuning.h4">
  15322. <phrase id="fiber.tuning.spin_wait_loop"/><link linkend="fiber.tuning.spin_wait_loop">Spin-wait
  15323. loop</link>
  15324. </bridgehead>
  15325. <para>
  15326. A lock is considered under contention, if a thread repeatedly fails to acquire
  15327. the lock because some other thread was faster. Waiting for a short time lets
  15328. other threads finish before trying to enter the critical section again. While
  15329. busy waiting on the lock, relaxing the CPU (via pause/yield mnemonic) gives
  15330. the CPU a hint that the code is in a spin-wait loop.
  15331. </para>
  15332. <itemizedlist>
  15333. <listitem>
  15334. <simpara>
  15335. prevents expensive pipeline flushes (speculatively executed load and compare
  15336. instructions are not pushed to pipeline)
  15337. </simpara>
  15338. </listitem>
  15339. <listitem>
  15340. <simpara>
  15341. another hardware thread (simultaneous multithreading) can get time slice
  15342. </simpara>
  15343. </listitem>
  15344. <listitem>
  15345. <simpara>
  15346. it does delay a few CPU cycles, but this is necessary to prevent starvation
  15347. </simpara>
  15348. </listitem>
  15349. </itemizedlist>
  15350. <para>
  15351. It is obvious that this strategy is useless on single core systems because
  15352. the lock can only released if the thread gives up its time slice in order to
  15353. let other threads run. The macro BOOST_FIBERS_SPIN_SINGLE_CORE replaces the
  15354. CPU hints (pause/yield mnemonic) by informing the operating system (via <code><phrase
  15355. role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">this_thread_yield</phrase><phrase
  15356. role="special">()</phrase></code>) that the thread gives up its time slice
  15357. and the operating system switches to another thread.
  15358. </para>
  15359. <bridgehead renderas="sect3" id="fiber.tuning.h5">
  15360. <phrase id="fiber.tuning.exponential_back_off"/><link linkend="fiber.tuning.exponential_back_off">Exponential
  15361. back-off</link>
  15362. </bridgehead>
  15363. <para>
  15364. The macro BOOST_FIBERS_RETRY_THRESHOLD determines how many times the CPU iterates
  15365. in the spin-wait loop before yielding the thread or blocking in futex-wait.
  15366. The spinlock tracks how many times the thread failed to acquire the lock. The
  15367. higher the contention, the longer the thread should back-off. A <quote>Binary
  15368. Exponential Backoff</quote> algorithm together with a randomized contention
  15369. window is utilized for this purpose. BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD
  15370. determines the upper limit of the contention window (expressed as the exponent
  15371. for basis of two).
  15372. </para>
  15373. <bridgehead renderas="sect3" id="fiber.tuning.h6">
  15374. <phrase id="fiber.tuning.speculative_execution__hardware_transactional_memory_"/><link
  15375. linkend="fiber.tuning.speculative_execution__hardware_transactional_memory_">Speculative
  15376. execution (hardware transactional memory)</link>
  15377. </bridgehead>
  15378. <para>
  15379. Boost.Fiber uses spinlocks to protect critical regions that can be used together
  15380. with transactional memory (see section <link linkend="speculation">Speculative
  15381. execution</link>).
  15382. </para>
  15383. <note>
  15384. <para>
  15385. TXS is enabled if property <code><phrase role="identifier">htm</phrase><phrase
  15386. role="special">=</phrase><phrase role="identifier">tsx</phrase></code> is
  15387. specified at b2 command-line and <code><phrase role="identifier">BOOST_USE_TSX</phrase></code>
  15388. is applied to the compiler.
  15389. </para>
  15390. </note>
  15391. <note>
  15392. <para>
  15393. A TSX-transaction will be aborted if the floating point state is modified
  15394. inside a critical region. As a consequence floating point operations, e.g.
  15395. tore/load of floating point related registers during a fiber (context) switch
  15396. are disabled.
  15397. </para>
  15398. </note>
  15399. <bridgehead renderas="sect3" id="fiber.tuning.h7">
  15400. <phrase id="fiber.tuning.numa_systems"/><link linkend="fiber.tuning.numa_systems">NUMA
  15401. systems</link>
  15402. </bridgehead>
  15403. <para>
  15404. Modern multi-socket systems are usually designed as <link linkend="numa">NUMA
  15405. systems</link>. A suitable fiber scheduler like <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link> reduces
  15406. remote memory access (latence).
  15407. </para>
  15408. <bridgehead renderas="sect3" id="fiber.tuning.h8">
  15409. <phrase id="fiber.tuning.parameters"/><link linkend="fiber.tuning.parameters">Parameters</link>
  15410. </bridgehead>
  15411. <table frame="all" id="fiber.tuning.parameters_that_migh_be_defiend_at_compiler_s_command_line">
  15412. <title>Parameters that migh be defiend at compiler's command line</title>
  15413. <tgroup cols="3">
  15414. <thead>
  15415. <row>
  15416. <entry>
  15417. <para>
  15418. Parameter
  15419. </para>
  15420. </entry>
  15421. <entry>
  15422. <para>
  15423. Default value
  15424. </para>
  15425. </entry>
  15426. <entry>
  15427. <para>
  15428. Effect on Boost.Fiber
  15429. </para>
  15430. </entry>
  15431. </row>
  15432. </thead>
  15433. <tbody>
  15434. <row>
  15435. <entry>
  15436. <para>
  15437. BOOST_FIBERS_NO_ATOMICS
  15438. </para>
  15439. </entry>
  15440. <entry>
  15441. <para>
  15442. -
  15443. </para>
  15444. </entry>
  15445. <entry>
  15446. <para>
  15447. no multithreading support, all atomics removed, no synchronization
  15448. between fibers running in different threads
  15449. </para>
  15450. </entry>
  15451. </row>
  15452. <row>
  15453. <entry>
  15454. <para>
  15455. BOOST_FIBERS_SPINLOCK_STD_MUTEX
  15456. </para>
  15457. </entry>
  15458. <entry>
  15459. <para>
  15460. -
  15461. </para>
  15462. </entry>
  15463. <entry>
  15464. <para>
  15465. <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  15466. role="identifier">mutex</phrase></code> used inside spinlock
  15467. </para>
  15468. </entry>
  15469. </row>
  15470. <row>
  15471. <entry>
  15472. <para>
  15473. BOOST_FIBERS_SPINLOCK_TTAS
  15474. </para>
  15475. </entry>
  15476. <entry>
  15477. <para>
  15478. +
  15479. </para>
  15480. </entry>
  15481. <entry>
  15482. <para>
  15483. spinlock with test-test-and-swap on shared variable
  15484. </para>
  15485. </entry>
  15486. </row>
  15487. <row>
  15488. <entry>
  15489. <para>
  15490. BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE
  15491. </para>
  15492. </entry>
  15493. <entry>
  15494. <para>
  15495. -
  15496. </para>
  15497. </entry>
  15498. <entry>
  15499. <para>
  15500. spinlock with test-test-and-swap on shared variable, adaptive retries
  15501. while busy waiting
  15502. </para>
  15503. </entry>
  15504. </row>
  15505. <row>
  15506. <entry>
  15507. <para>
  15508. BOOST_FIBERS_SPINLOCK_TTAS_FUTEX
  15509. </para>
  15510. </entry>
  15511. <entry>
  15512. <para>
  15513. -
  15514. </para>
  15515. </entry>
  15516. <entry>
  15517. <para>
  15518. spinlock with test-test-and-swap on shared variable, suspend on futex
  15519. after certain number of retries
  15520. </para>
  15521. </entry>
  15522. </row>
  15523. <row>
  15524. <entry>
  15525. <para>
  15526. BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX
  15527. </para>
  15528. </entry>
  15529. <entry>
  15530. <para>
  15531. -
  15532. </para>
  15533. </entry>
  15534. <entry>
  15535. <para>
  15536. spinlock with test-test-and-swap on shared variable, while busy waiting
  15537. adaptive retries, suspend on futex certain amount of retries
  15538. </para>
  15539. </entry>
  15540. </row>
  15541. <row>
  15542. <entry>
  15543. <para>
  15544. BOOST_FIBERS_SPINLOCK_TTAS + BOOST_USE_TSX
  15545. </para>
  15546. </entry>
  15547. <entry>
  15548. <para>
  15549. -
  15550. </para>
  15551. </entry>
  15552. <entry>
  15553. <para>
  15554. spinlock with test-test-and-swap and speculative execution (Intel
  15555. TSX required)
  15556. </para>
  15557. </entry>
  15558. </row>
  15559. <row>
  15560. <entry>
  15561. <para>
  15562. BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE + BOOST_USE_TSX
  15563. </para>
  15564. </entry>
  15565. <entry>
  15566. <para>
  15567. -
  15568. </para>
  15569. </entry>
  15570. <entry>
  15571. <para>
  15572. spinlock with test-test-and-swap on shared variable, adaptive retries
  15573. while busy waiting and speculative execution (Intel TSX required)
  15574. </para>
  15575. </entry>
  15576. </row>
  15577. <row>
  15578. <entry>
  15579. <para>
  15580. BOOST_FIBERS_SPINLOCK_TTAS_FUTEX + BOOST_USE_TSX
  15581. </para>
  15582. </entry>
  15583. <entry>
  15584. <para>
  15585. -
  15586. </para>
  15587. </entry>
  15588. <entry>
  15589. <para>
  15590. spinlock with test-test-and-swap on shared variable, suspend on futex
  15591. after certain number of retries and speculative execution (Intel
  15592. TSX required)
  15593. </para>
  15594. </entry>
  15595. </row>
  15596. <row>
  15597. <entry>
  15598. <para>
  15599. BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX + BOOST_USE_TSX
  15600. </para>
  15601. </entry>
  15602. <entry>
  15603. <para>
  15604. -
  15605. </para>
  15606. </entry>
  15607. <entry>
  15608. <para>
  15609. spinlock with test-test-and-swap on shared variable, while busy waiting
  15610. adaptive retries, suspend on futex certain amount of retries and
  15611. speculative execution (Intel TSX required)
  15612. </para>
  15613. </entry>
  15614. </row>
  15615. <row>
  15616. <entry>
  15617. <para>
  15618. BOOST_FIBERS_SPIN_SINGLE_CORE
  15619. </para>
  15620. </entry>
  15621. <entry>
  15622. <para>
  15623. -
  15624. </para>
  15625. </entry>
  15626. <entry>
  15627. <para>
  15628. on single core machines with multiple threads, yield thread (<code><phrase
  15629. role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  15630. role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase
  15631. role="identifier">yield</phrase><phrase role="special">()</phrase></code>)
  15632. after collisions
  15633. </para>
  15634. </entry>
  15635. </row>
  15636. <row>
  15637. <entry>
  15638. <para>
  15639. BOOST_FIBERS_RETRY_THRESHOLD
  15640. </para>
  15641. </entry>
  15642. <entry>
  15643. <para>
  15644. 64
  15645. </para>
  15646. </entry>
  15647. <entry>
  15648. <para>
  15649. max number of retries while busy spinning, the use fallback
  15650. </para>
  15651. </entry>
  15652. </row>
  15653. <row>
  15654. <entry>
  15655. <para>
  15656. BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD
  15657. </para>
  15658. </entry>
  15659. <entry>
  15660. <para>
  15661. 16
  15662. </para>
  15663. </entry>
  15664. <entry>
  15665. <para>
  15666. max size of collisions window, expressed as exponent for the basis
  15667. of two
  15668. </para>
  15669. </entry>
  15670. </row>
  15671. <row>
  15672. <entry>
  15673. <para>
  15674. BOOST_FIBERS_SPIN_BEFORE_SLEEP0
  15675. </para>
  15676. </entry>
  15677. <entry>
  15678. <para>
  15679. 32
  15680. </para>
  15681. </entry>
  15682. <entry>
  15683. <para>
  15684. max number of retries that relax the processor before the thread
  15685. sleeps for 0s
  15686. </para>
  15687. </entry>
  15688. </row>
  15689. <row>
  15690. <entry>
  15691. <para>
  15692. BOOST_FIBERS_SPIN_BEFORE_YIELD
  15693. </para>
  15694. </entry>
  15695. <entry>
  15696. <para>
  15697. 64
  15698. </para>
  15699. </entry>
  15700. <entry>
  15701. <para>
  15702. max number of retries where the thread sleeps for 0s before yield
  15703. thread (<code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  15704. role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase
  15705. role="identifier">yield</phrase><phrase role="special">()</phrase></code>)
  15706. </para>
  15707. </entry>
  15708. </row>
  15709. </tbody>
  15710. </tgroup>
  15711. </table>
  15712. </section>
  15713. <section id="fiber.custom">
  15714. <title><anchor id="custom"/><link linkend="fiber.custom">Customization</link></title>
  15715. <bridgehead renderas="sect3" id="fiber.custom.h0">
  15716. <phrase id="fiber.custom.overview"/><link linkend="fiber.custom.overview">Overview</link>
  15717. </bridgehead>
  15718. <para>
  15719. As noted in the <link linkend="scheduling">Scheduling</link> section, by default
  15720. <emphasis role="bold">Boost.Fiber</emphasis> uses its own <link linkend="class_round_robin"><code>round_robin</code></link> scheduler
  15721. for each thread. To control the way <emphasis role="bold">Boost.Fiber</emphasis>
  15722. schedules ready fibers on a particular thread, in general you must follow several
  15723. steps. This section discusses those steps, whereas <link linkend="scheduling">Scheduling</link>
  15724. serves as a reference for the classes involved.
  15725. </para>
  15726. <para>
  15727. The library's fiber manager keeps track of suspended (blocked) fibers. Only
  15728. when a fiber becomes ready to run is it passed to the scheduler. Of course,
  15729. if there are fewer than two ready fibers, the scheduler's job is trivial. Only
  15730. when there are two or more ready fibers does the particular scheduler implementation
  15731. start to influence the overall sequence of fiber execution.
  15732. </para>
  15733. <para>
  15734. In this section we illustrate a simple custom scheduler that honors an integer
  15735. fiber priority. We will implement it such that a fiber with higher priority
  15736. is preferred over a fiber with lower priority. Any fibers with equal priority
  15737. values are serviced on a round-robin basis.
  15738. </para>
  15739. <para>
  15740. The full source code for the examples below is found in <ulink url="../../examples/priority.cpp">priority.cpp</ulink>.
  15741. </para>
  15742. <bridgehead renderas="sect3" id="fiber.custom.h1">
  15743. <phrase id="fiber.custom.custom_property_class"/><link linkend="fiber.custom.custom_property_class">Custom
  15744. Property Class</link>
  15745. </bridgehead>
  15746. <para>
  15747. The first essential point is that we must associate an integer priority with
  15748. each fiber.<footnote id="fiber.custom.f0">
  15749. <para>
  15750. A previous version of the Fiber library implicitly tracked an int priority
  15751. for each fiber, even though the default scheduler ignored it. This has been
  15752. dropped, since the library now supports arbitrary scheduler-specific fiber
  15753. properties.
  15754. </para>
  15755. </footnote>
  15756. </para>
  15757. <para>
  15758. One might suggest deriving a custom <link linkend="class_fiber"><code>fiber</code></link> subclass to store such
  15759. properties. There are a couple of reasons for the present mechanism.
  15760. </para>
  15761. <orderedlist>
  15762. <listitem>
  15763. <simpara>
  15764. <emphasis role="bold">Boost.Fiber</emphasis> provides a number of different
  15765. ways to launch a fiber. (Consider <link linkend="fibers_async"><code>fibers::async()</code></link>.) Higher-level
  15766. libraries might introduce additional such wrapper functions. A custom scheduler
  15767. must associate its custom properties with <emphasis>every</emphasis> fiber
  15768. in the thread, not only the ones explicitly launched by instantiating a
  15769. custom <code><phrase role="identifier">fiber</phrase></code> subclass.
  15770. </simpara>
  15771. </listitem>
  15772. <listitem>
  15773. <simpara>
  15774. Consider a large existing program that launches fibers in many different
  15775. places in the code. We discover a need to introduce a custom scheduler
  15776. for a particular thread. If supporting that scheduler's custom properties
  15777. required a particular <code><phrase role="identifier">fiber</phrase></code>
  15778. subclass, we would have to hunt down and modify every place that launches
  15779. a fiber on that thread.
  15780. </simpara>
  15781. </listitem>
  15782. <listitem>
  15783. <simpara>
  15784. The <link linkend="class_fiber"><code>fiber</code></link> class is actually just a handle to internal <link linkend="class_context"><code>context</code></link> data.
  15785. A subclass of <code><phrase role="identifier">fiber</phrase></code> would
  15786. not add data to <code><phrase role="identifier">context</phrase></code>.
  15787. </simpara>
  15788. </listitem>
  15789. </orderedlist>
  15790. <para>
  15791. The present mechanism allows you to <quote>drop in</quote> a custom scheduler
  15792. with its attendant custom properties <emphasis>without</emphasis> altering
  15793. the rest of your application.
  15794. </para>
  15795. <para>
  15796. Instead of deriving a custom scheduler fiber properties subclass from <link linkend="class_fiber"><code>fiber</code></link>,
  15797. you must instead derive it from <link linkend="class_fiber_properties"><code>fiber_properties</code></link>.
  15798. </para>
  15799. <para>
  15800. <programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber_properties</phrase> <phrase role="special">{</phrase>
  15801. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  15802. <phrase role="identifier">priority_props</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">):</phrase>
  15803. <phrase role="identifier">fiber_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">),</phrase> <co id="fiber.custom.c0" linkends="fiber.custom.c1" />
  15804. <phrase role="identifier">priority_</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  15805. <phrase role="special">}</phrase>
  15806. <phrase role="keyword">int</phrase> <phrase role="identifier">get_priority</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
  15807. <phrase role="keyword">return</phrase> <phrase role="identifier">priority_</phrase><phrase role="special">;</phrase> <co id="fiber.custom.c2" linkends="fiber.custom.c3" />
  15808. <phrase role="special">}</phrase>
  15809. <phrase role="comment">// Call this method to alter priority, because we must notify</phrase>
  15810. <phrase role="comment">// priority_scheduler of any change.</phrase>
  15811. <phrase role="keyword">void</phrase> <phrase role="identifier">set_priority</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">p</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.custom.c4" linkends="fiber.custom.c5" />
  15812. <phrase role="comment">// Of course, it's only worth reshuffling the queue and all if we're</phrase>
  15813. <phrase role="comment">// actually changing the priority.</phrase>
  15814. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">p</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">priority_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  15815. <phrase role="identifier">priority_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">p</phrase><phrase role="special">;</phrase>
  15816. <phrase role="identifier">notify</phrase><phrase role="special">();</phrase>
  15817. <phrase role="special">}</phrase>
  15818. <phrase role="special">}</phrase>
  15819. <phrase role="comment">// The fiber name of course is solely for purposes of this example</phrase>
  15820. <phrase role="comment">// program; it has nothing to do with implementing scheduler priority.</phrase>
  15821. <phrase role="comment">// This is a public data member -- not requiring set/get access methods --</phrase>
  15822. <phrase role="comment">// because we need not inform the scheduler of any change.</phrase>
  15823. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">name</phrase><phrase role="special">;</phrase> <co id="fiber.custom.c6" linkends="fiber.custom.c7" />
  15824. <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
  15825. <phrase role="keyword">int</phrase> <phrase role="identifier">priority_</phrase><phrase role="special">;</phrase>
  15826. <phrase role="special">};</phrase>
  15827. </programlisting>
  15828. </para>
  15829. <calloutlist>
  15830. <callout arearefs="fiber.custom.c0" id="fiber.custom.c1">
  15831. <para>
  15832. Your subclass constructor must accept a <literal><link linkend="class_context"><code>context</code></link>*</literal>
  15833. and pass it to the <code><phrase role="identifier">fiber_properties</phrase></code>
  15834. constructor.
  15835. </para>
  15836. </callout>
  15837. <callout arearefs="fiber.custom.c2" id="fiber.custom.c3">
  15838. <para>
  15839. Provide read access methods at your own discretion.
  15840. </para>
  15841. </callout>
  15842. <callout arearefs="fiber.custom.c4" id="fiber.custom.c5">
  15843. <para>
  15844. It's important to call <code><phrase role="identifier">notify</phrase><phrase
  15845. role="special">()</phrase></code> on any change in a property that can
  15846. affect the scheduler's behavior. Therefore, such modifications should only
  15847. be performed through an access method.
  15848. </para>
  15849. </callout>
  15850. <callout arearefs="fiber.custom.c6" id="fiber.custom.c7">
  15851. <para>
  15852. A property that does not affect the scheduler does not need access methods.
  15853. </para>
  15854. </callout>
  15855. </calloutlist>
  15856. <bridgehead renderas="sect3" id="fiber.custom.h2">
  15857. <phrase id="fiber.custom.custom_scheduler_class"/><link linkend="fiber.custom.custom_scheduler_class">Custom
  15858. Scheduler Class</link>
  15859. </bridgehead>
  15860. <para>
  15861. Now we can derive a custom scheduler from <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link>,
  15862. specifying our custom property class <code><phrase role="identifier">priority_props</phrase></code>
  15863. as the template parameter.
  15864. </para>
  15865. <para>
  15866. <programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">priority_scheduler</phrase> <phrase role="special">:</phrase>
  15867. <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">algorithm_with_properties</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
  15868. <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
  15869. <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">scheduler</phrase><phrase role="special">::</phrase><phrase role="identifier">ready_queue_type</phrase><co id="fiber.custom.c8" linkends="fiber.custom.c9" /> <phrase role="identifier">rqueue_t</phrase><phrase role="special">;</phrase>
  15870. <phrase role="identifier">rqueue_t</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">;</phrase>
  15871. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">{};</phrase>
  15872. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase> <phrase role="identifier">cnd_</phrase><phrase role="special">{};</phrase>
  15873. <phrase role="keyword">bool</phrase> <phrase role="identifier">flag_</phrase><phrase role="special">{</phrase> <phrase role="keyword">false</phrase> <phrase role="special">};</phrase>
  15874. <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
  15875. <phrase role="identifier">priority_scheduler</phrase><phrase role="special">()</phrase> <phrase role="special">:</phrase>
  15876. <phrase role="identifier">rqueue_</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
  15877. <phrase role="special">}</phrase>
  15878. <phrase role="comment">// For a subclass of algorithm_with_properties&lt;&gt;, it's important to</phrase>
  15879. <phrase role="comment">// override the correct awakened() overload.</phrase>
  15880. <co id="fiber.custom.c10" linkends="fiber.custom.c11" /><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">,</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">props</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
  15881. <phrase role="keyword">int</phrase> <phrase role="identifier">ctx_priority</phrase> <phrase role="special">=</phrase> <phrase role="identifier">props</phrase><phrase role="special">.</phrase><phrase role="identifier">get_priority</phrase><phrase role="special">();</phrase> <co id="fiber.custom.c12" linkends="fiber.custom.c13" />
  15882. <phrase role="comment">// With this scheduler, fibers with higher priority values are</phrase>
  15883. <phrase role="comment">// preferred over fibers with lower priority values. But fibers with</phrase>
  15884. <phrase role="comment">// equal priority values are processed in round-robin fashion. So when</phrase>
  15885. <phrase role="comment">// we're handed a new context*, put it at the end of the fibers</phrase>
  15886. <phrase role="comment">// with that same priority. In other words: search for the first fiber</phrase>
  15887. <phrase role="comment">// in the queue with LOWER priority, and insert before that one.</phrase>
  15888. <phrase role="identifier">rqueue_t</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">i</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">find_if</phrase><phrase role="special">(</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">begin</phrase><phrase role="special">(),</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">end</phrase><phrase role="special">(),</phrase>
  15889. <phrase role="special">[</phrase><phrase role="identifier">ctx_priority</phrase><phrase role="special">,</phrase><phrase role="keyword">this</phrase><phrase role="special">](</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">c</phrase><phrase role="special">)</phrase>
  15890. <phrase role="special">{</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">properties</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase><phrase role="identifier">c</phrase> <phrase role="special">).</phrase><phrase role="identifier">get_priority</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">ctx_priority</phrase><phrase role="special">;</phrase> <phrase role="special">}));</phrase>
  15891. <phrase role="comment">// Now, whether or not we found a fiber with lower priority,</phrase>
  15892. <phrase role="comment">// insert this new fiber here.</phrase>
  15893. <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">insert</phrase><phrase role="special">(</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">);</phrase>
  15894. <phrase role="special">}</phrase>
  15895. <co id="fiber.custom.c14" linkends="fiber.custom.c15" /><phrase role="keyword">virtual</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
  15896. <phrase role="comment">// if ready queue is empty, just tell caller</phrase>
  15897. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">empty</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
  15898. <phrase role="keyword">return</phrase> <phrase role="keyword">nullptr</phrase><phrase role="special">;</phrase>
  15899. <phrase role="special">}</phrase>
  15900. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">front</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
  15901. <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">pop_front</phrase><phrase role="special">();</phrase>
  15902. <phrase role="keyword">return</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase>
  15903. <phrase role="special">}</phrase>
  15904. <co id="fiber.custom.c16" linkends="fiber.custom.c17" /><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
  15905. <phrase role="keyword">return</phrase> <phrase role="special">!</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">empty</phrase><phrase role="special">();</phrase>
  15906. <phrase role="special">}</phrase>
  15907. <co id="fiber.custom.c18" linkends="fiber.custom.c19" /><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">property_change</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">,</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">props</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
  15908. <phrase role="comment">// Although our priority_props class defines multiple properties, only</phrase>
  15909. <phrase role="comment">// one of them (priority) actually calls notify() when changed. The</phrase>
  15910. <phrase role="comment">// point of a property_change() override is to reshuffle the ready</phrase>
  15911. <phrase role="comment">// queue according to the updated priority value.</phrase>
  15912. <phrase role="comment">// 'ctx' might not be in our queue at all, if caller is changing the</phrase>
  15913. <phrase role="comment">// priority of (say) the running fiber. If it's not there, no need to</phrase>
  15914. <phrase role="comment">// move it: we'll handle it next time it hits awakened().</phrase>
  15915. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">ready_is_linked</phrase><phrase role="special">())</phrase> <phrase role="special">{</phrase> <co id="fiber.custom.c20" linkends="fiber.custom.c21" />
  15916. <phrase role="keyword">return</phrase><phrase role="special">;</phrase>
  15917. <phrase role="special">}</phrase>
  15918. <phrase role="comment">// Found ctx: unlink it</phrase>
  15919. <phrase role="identifier">ctx</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">ready_unlink</phrase><phrase role="special">();</phrase>
  15920. <phrase role="comment">// Here we know that ctx was in our ready queue, but we've unlinked</phrase>
  15921. <phrase role="comment">// it. We happen to have a method that will (re-)add a context* to the</phrase>
  15922. <phrase role="comment">// right place in the ready queue.</phrase>
  15923. <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">,</phrase> <phrase role="identifier">props</phrase><phrase role="special">);</phrase>
  15924. <phrase role="special">}</phrase>
  15925. <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">time_point</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
  15926. <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">::</phrase><phrase role="identifier">max</phrase><phrase role="special">)()</phrase> <phrase role="special">==</phrase> <phrase role="identifier">time_point</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  15927. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">);</phrase>
  15928. <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="special">[</phrase><phrase role="keyword">this</phrase><phrase role="special">](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">flag_</phrase><phrase role="special">;</phrase> <phrase role="special">});</phrase>
  15929. <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
  15930. <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
  15931. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">);</phrase>
  15932. <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">time_point</phrase><phrase role="special">,</phrase> <phrase role="special">[</phrase><phrase role="keyword">this</phrase><phrase role="special">](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">flag_</phrase><phrase role="special">;</phrase> <phrase role="special">});</phrase>
  15933. <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
  15934. <phrase role="special">}</phrase>
  15935. <phrase role="special">}</phrase>
  15936. <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
  15937. <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">);</phrase>
  15938. <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
  15939. <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
  15940. <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase>
  15941. <phrase role="special">}</phrase>
  15942. <phrase role="special">};</phrase>
  15943. </programlisting>
  15944. </para>
  15945. <calloutlist>
  15946. <callout arearefs="fiber.custom.c8" id="fiber.custom.c9">
  15947. <para>
  15948. See <link linkend="ready_queue_t">ready_queue_t</link>.
  15949. </para>
  15950. </callout>
  15951. <callout arearefs="fiber.custom.c10" id="fiber.custom.c11">
  15952. <para>
  15953. You must override the <link linkend="algorithm_with_properties_awakened"><code>algorithm_with_properties::awakened()</code></link>
  15954. method.
  15955. This is how your scheduler receives notification of a fiber that has become
  15956. ready to run.
  15957. </para>
  15958. </callout>
  15959. <callout arearefs="fiber.custom.c12" id="fiber.custom.c13">
  15960. <para>
  15961. <code><phrase role="identifier">props</phrase></code> is the instance of
  15962. priority_props associated with the passed fiber <code><phrase role="identifier">ctx</phrase></code>.
  15963. </para>
  15964. </callout>
  15965. <callout arearefs="fiber.custom.c14" id="fiber.custom.c15">
  15966. <para>
  15967. You must override the <link linkend="algorithm_with_properties_pick_next"><code>algorithm_with_properties::pick_next()</code></link>
  15968. method.
  15969. This is how your scheduler actually advises the fiber manager of the next
  15970. fiber to run.
  15971. </para>
  15972. </callout>
  15973. <callout arearefs="fiber.custom.c16" id="fiber.custom.c17">
  15974. <para>
  15975. You must override <link linkend="algorithm_with_properties_has_ready_fibers"><code>algorithm_with_properties::has_ready_fibers()</code></link>
  15976. to
  15977. inform the fiber manager of the state of your ready queue.
  15978. </para>
  15979. </callout>
  15980. <callout arearefs="fiber.custom.c18" id="fiber.custom.c19">
  15981. <para>
  15982. Overriding <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link>
  15983. is
  15984. optional. This override handles the case in which the running fiber changes
  15985. the priority of another ready fiber: a fiber already in our queue. In that
  15986. case, move the updated fiber within the queue.
  15987. </para>
  15988. </callout>
  15989. <callout arearefs="fiber.custom.c20" id="fiber.custom.c21">
  15990. <para>
  15991. Your <code><phrase role="identifier">property_change</phrase><phrase role="special">()</phrase></code>
  15992. override must be able to handle the case in which the passed <code><phrase
  15993. role="identifier">ctx</phrase></code> is not in your ready queue. It might
  15994. be running, or it might be blocked.
  15995. </para>
  15996. </callout>
  15997. </calloutlist>
  15998. <para>
  15999. Our example <code><phrase role="identifier">priority_scheduler</phrase></code>
  16000. doesn't override <link linkend="algorithm_with_properties_new_properties"><code>algorithm_with_properties::new_properties()</code></link>:
  16001. we're content with allocating <code><phrase role="identifier">priority_props</phrase></code>
  16002. instances on the heap.
  16003. </para>
  16004. <bridgehead renderas="sect3" id="fiber.custom.h3">
  16005. <phrase id="fiber.custom.replace_default_scheduler"/><link linkend="fiber.custom.replace_default_scheduler">Replace
  16006. Default Scheduler</link>
  16007. </bridgehead>
  16008. <para>
  16009. You must call <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link> at the start
  16010. of each thread on which you want <emphasis role="bold">Boost.Fiber</emphasis>
  16011. to use your custom scheduler rather than its own default <link linkend="class_round_robin"><code>round_robin</code></link>.
  16012. Specifically, you must call <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
  16013. role="special">()</phrase></code> before performing any other <emphasis role="bold">Boost.Fiber</emphasis>
  16014. operations on that thread.
  16015. </para>
  16016. <para>
  16017. <programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase><phrase role="identifier">argv</phrase><phrase role="special">[])</phrase> <phrase role="special">{</phrase>
  16018. <phrase role="comment">// make sure we use our priority_scheduler rather than default round_robin</phrase>
  16019. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">priority_scheduler</phrase> <phrase role="special">&gt;();</phrase>
  16020. <phrase role="special">...</phrase>
  16021. <phrase role="special">}</phrase>
  16022. </programlisting>
  16023. </para>
  16024. <bridgehead renderas="sect3" id="fiber.custom.h4">
  16025. <phrase id="fiber.custom.use_properties"/><link linkend="fiber.custom.use_properties">Use
  16026. Properties</link>
  16027. </bridgehead>
  16028. <para>
  16029. The running fiber can access its own <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass
  16030. instance by calling <link linkend="this_fiber_properties"><code>this_fiber::properties()</code></link>. Although
  16031. <code><phrase role="identifier">properties</phrase><phrase role="special">&lt;&gt;()</phrase></code>
  16032. is a nullary function, you must pass, as a template parameter, the <code><phrase
  16033. role="identifier">fiber_properties</phrase></code> subclass.
  16034. </para>
  16035. <para>
  16036. <programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">properties</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">&gt;().</phrase><phrase role="identifier">name</phrase> <phrase role="special">=</phrase> <phrase role="string">&quot;main&quot;</phrase><phrase role="special">;</phrase>
  16037. </programlisting>
  16038. </para>
  16039. <para>
  16040. Given a <link linkend="class_fiber"><code>fiber</code></link> instance still connected with a running fiber (that
  16041. is, not <link linkend="fiber_detach"><code>fiber::detach()</code></link>ed), you may access that fiber's properties
  16042. using <link linkend="fiber_properties"><code>fiber::properties()</code></link>. As with <code><phrase role="identifier">boost</phrase><phrase
  16043. role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase
  16044. role="special">::</phrase><phrase role="identifier">properties</phrase><phrase
  16045. role="special">&lt;&gt;()</phrase></code>, you must pass your <code><phrase
  16046. role="identifier">fiber_properties</phrase></code> subclass as the template
  16047. parameter.
  16048. </para>
  16049. <para>
  16050. <programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;</phrase>
  16051. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">launch</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">func</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">name</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">priority</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
  16052. <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">func</phrase><phrase role="special">);</phrase>
  16053. <phrase role="identifier">priority_props</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">props</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">.</phrase><phrase role="identifier">properties</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
  16054. <phrase role="identifier">props</phrase><phrase role="special">.</phrase><phrase role="identifier">name</phrase> <phrase role="special">=</phrase> <phrase role="identifier">name</phrase><phrase role="special">;</phrase>
  16055. <phrase role="identifier">props</phrase><phrase role="special">.</phrase><phrase role="identifier">set_priority</phrase><phrase role="special">(</phrase> <phrase role="identifier">priority</phrase><phrase role="special">);</phrase>
  16056. <phrase role="keyword">return</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">;</phrase>
  16057. <phrase role="special">}</phrase>
  16058. </programlisting>
  16059. </para>
  16060. <para>
  16061. Launching a new fiber schedules that fiber as ready, but does <emphasis>not</emphasis>
  16062. immediately enter its <emphasis>fiber-function</emphasis>. The current fiber
  16063. retains control until it blocks (or yields, or terminates) for some other reason.
  16064. As shown in the <code><phrase role="identifier">launch</phrase><phrase role="special">()</phrase></code>
  16065. function above, it is reasonable to launch a fiber and immediately set relevant
  16066. properties -- such as, for instance, its priority. Your custom scheduler can
  16067. then make use of this information next time the fiber manager calls <link linkend="algorithm_with_properties_pick_next"><code>algorithm_with_properties::pick_next()</code></link>.
  16068. </para>
  16069. </section>
  16070. <section id="fiber.rationale">
  16071. <title><link linkend="fiber.rationale">Rationale</link></title>
  16072. <bridgehead renderas="sect3" id="fiber.rationale.h0">
  16073. <phrase id="fiber.rationale.preprocessor_defines"/><link linkend="fiber.rationale.preprocessor_defines">preprocessor
  16074. defines</link>
  16075. </bridgehead>
  16076. <table frame="all" id="fiber.rationale.preopcessor_defines">
  16077. <title>preopcessor defines</title>
  16078. <tgroup cols="2">
  16079. <thead>
  16080. <row>
  16081. <entry>
  16082. </entry>
  16083. <entry>
  16084. </entry>
  16085. </row>
  16086. </thead>
  16087. <tbody>
  16088. <row>
  16089. <entry>
  16090. <para>
  16091. BOOST_FIBERS_NO_ATOMICS
  16092. </para>
  16093. </entry>
  16094. <entry>
  16095. <para>
  16096. no <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  16097. role="identifier">atomic</phrase><phrase role="special">&lt;&gt;</phrase></code>
  16098. used, inter-thread synchronization disabled
  16099. </para>
  16100. </entry>
  16101. </row>
  16102. <row>
  16103. <entry>
  16104. <para>
  16105. BOOST_FIBERS_SPINLOCK_STD_MUTEX
  16106. </para>
  16107. </entry>
  16108. <entry>
  16109. <para>
  16110. use <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
  16111. role="identifier">mutex</phrase></code> as spinlock instead of default
  16112. <code><phrase role="identifier">XCHG</phrase></code>-sinlock with
  16113. backoff
  16114. </para>
  16115. </entry>
  16116. </row>
  16117. <row>
  16118. <entry>
  16119. <para>
  16120. BOOST_FIBERS_SPIN_BACKOFF
  16121. </para>
  16122. </entry>
  16123. <entry>
  16124. <para>
  16125. limit determines when to used <code><phrase role="identifier">std</phrase><phrase
  16126. role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase
  16127. role="special">::</phrase><phrase role="identifier">yield</phrase><phrase
  16128. role="special">()</phrase></code> instead of mnemonic <code><phrase
  16129. role="identifier">pause</phrase><phrase role="special">/</phrase><phrase
  16130. role="identifier">yield</phrase></code> during busy wait (apllies
  16131. on to <code><phrase role="identifier">XCHG</phrase></code>-spinlock)
  16132. </para>
  16133. </entry>
  16134. </row>
  16135. <row>
  16136. <entry>
  16137. <para>
  16138. BOOST_FIBERS_SINGLE_CORE
  16139. </para>
  16140. </entry>
  16141. <entry>
  16142. <para>
  16143. allways call <code><phrase role="identifier">std</phrase><phrase
  16144. role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase
  16145. role="special">::</phrase><phrase role="identifier">yield</phrase><phrase
  16146. role="special">()</phrase></code> without backoff during busy wait
  16147. (apllies on to <code><phrase role="identifier">XCHG</phrase></code>-spinlock)
  16148. </para>
  16149. </entry>
  16150. </row>
  16151. </tbody>
  16152. </tgroup>
  16153. </table>
  16154. <bridgehead renderas="sect3" id="fiber.rationale.h1">
  16155. <phrase id="fiber.rationale.distinction_between_coroutines_and_fibers"/><link
  16156. linkend="fiber.rationale.distinction_between_coroutines_and_fibers">distinction
  16157. between coroutines and fibers</link>
  16158. </bridgehead>
  16159. <para>
  16160. The fiber library extends the coroutine library by adding a scheduler and synchronization
  16161. mechanisms.
  16162. </para>
  16163. <itemizedlist>
  16164. <listitem>
  16165. <simpara>
  16166. a coroutine yields
  16167. </simpara>
  16168. </listitem>
  16169. <listitem>
  16170. <simpara>
  16171. a fiber blocks
  16172. </simpara>
  16173. </listitem>
  16174. </itemizedlist>
  16175. <para>
  16176. When a coroutine yields, it passes control directly to its caller (or, in the
  16177. case of symmetric coroutines, a designated other coroutine). When a fiber blocks,
  16178. it implicitly passes control to the fiber scheduler. Coroutines have no scheduler
  16179. because they need no scheduler.<footnote id="fiber.rationale.f0">
  16180. <para>
  16181. <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4024.pdf">'N4024:
  16182. Distinguishing coroutines and fibers'</ulink>
  16183. </para>
  16184. </footnote>.
  16185. </para>
  16186. <bridgehead renderas="sect3" id="fiber.rationale.h2">
  16187. <phrase id="fiber.rationale.what_about_transactional_memory"/><link linkend="fiber.rationale.what_about_transactional_memory">what
  16188. about transactional memory</link>
  16189. </bridgehead>
  16190. <para>
  16191. GCC supports transactional memory since version 4.7. Unfortunately tests show
  16192. that transactional memory is slower (ca. 4x) than spinlocks using atomics.
  16193. Once transactional memory is improved (supporting hybrid tm), spinlocks will
  16194. be replaced by __transaction_atomic{} statements surrounding the critical sections.
  16195. </para>
  16196. <bridgehead renderas="sect3" id="fiber.rationale.h3">
  16197. <phrase id="fiber.rationale.synchronization_between_fibers_running_in_different_threads"/><link
  16198. linkend="fiber.rationale.synchronization_between_fibers_running_in_different_threads">synchronization
  16199. between fibers running in different threads</link>
  16200. </bridgehead>
  16201. <para>
  16202. Synchronization classes from <ulink url="http://www.boost.org/doc/libs/release/libs/thread/index.html">Boost.Thread</ulink>
  16203. block the entire thread. In contrast, the synchronization classes from <emphasis
  16204. role="bold">Boost.Fiber</emphasis> block only specific fibers, so that the
  16205. scheduler can still keep the thread busy running other fibers in the meantime.
  16206. The synchronization classes from <emphasis role="bold">Boost.Fiber</emphasis>
  16207. are designed to be thread-safe, i.e. it is possible to synchronize fibers running
  16208. in different threads as well as fibers running in the same thread. (However,
  16209. there is a build option to disable cross-thread fiber synchronization support;
  16210. see <link linkend="cross_thread_sync">this description</link>.)
  16211. </para>
  16212. <anchor id="spurious_wakeup"/>
  16213. <bridgehead renderas="sect3" id="fiber.rationale.h4">
  16214. <phrase id="fiber.rationale.spurious_wakeup"/><link linkend="fiber.rationale.spurious_wakeup">spurious
  16215. wakeup</link>
  16216. </bridgehead>
  16217. <para>
  16218. Spurious wakeup can happen when using <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable"><code><phrase
  16219. role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code></ulink>:
  16220. the condition variable appears to be have been signaled while the awaited condition
  16221. may still be false. Spurious wakeup can happen repeatedly and is caused on
  16222. some multiprocessor systems where making <code><phrase role="identifier">std</phrase><phrase
  16223. role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code>
  16224. wakeup completely predictable would slow down all <code><phrase role="identifier">std</phrase><phrase
  16225. role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code>
  16226. operations.<footnote id="fiber.rationale.f1">
  16227. <para>
  16228. David R. Butenhof <quote>Programming with POSIX Threads</quote>
  16229. </para>
  16230. </footnote>
  16231. </para>
  16232. <para>
  16233. <link linkend="class_condition_variable"><code>condition_variable</code></link> is not subject to spurious wakeup.
  16234. Nonetheless it is prudent to test the business-logic condition in a <code><phrase
  16235. role="identifier">wait</phrase><phrase role="special">()</phrase></code> loop
  16236. &mdash; or, equivalently, use one of the <code><phrase role="identifier">wait</phrase><phrase
  16237. role="special">(</phrase> <phrase role="identifier">lock</phrase><phrase role="special">,</phrase>
  16238. <phrase role="identifier">predicate</phrase> <phrase role="special">)</phrase></code>
  16239. overloads.
  16240. </para>
  16241. <para>
  16242. See also <link linkend="condition_variable_spurious_wakeups">No Spurious Wakeups</link>.
  16243. </para>
  16244. <bridgehead renderas="sect3" id="fiber.rationale.h5">
  16245. <phrase id="fiber.rationale.migrating_fibers_between_threads"/><link linkend="fiber.rationale.migrating_fibers_between_threads">migrating
  16246. fibers between threads</link>
  16247. </bridgehead>
  16248. <para>
  16249. Support for migrating fibers between threads has been integrated. The user-defined
  16250. scheduler must call <link linkend="context_detach"><code>context::detach()</code></link> on a fiber-context on the
  16251. source thread and <link linkend="context_attach"><code>context::attach()</code></link> on the destination thread,
  16252. passing the fiber-context to migrate. (For more information about custom schedulers,
  16253. see <link linkend="custom">Customization</link>.) Examples <code><phrase role="identifier">work_sharing</phrase></code>
  16254. and <code><phrase role="identifier">work_stealing</phrase></code> in directory
  16255. <code><phrase role="identifier">examples</phrase></code> might be used as a
  16256. blueprint.
  16257. </para>
  16258. <para>
  16259. See also <link linkend="migration">Migrating fibers between threads</link>.
  16260. </para>
  16261. <bridgehead renderas="sect3" id="fiber.rationale.h6">
  16262. <phrase id="fiber.rationale.support_for_boost_asio"/><link linkend="fiber.rationale.support_for_boost_asio">support
  16263. for Boost.Asio</link>
  16264. </bridgehead>
  16265. <para>
  16266. Support for <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>&#8217;s
  16267. <emphasis>async-result</emphasis> is not part of the official API. However,
  16268. to integrate with a <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service.html"><code><phrase
  16269. role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase
  16270. role="special">::</phrase><phrase role="identifier">io_service</phrase></code></ulink>,
  16271. see <link linkend="integration">Sharing a Thread with Another Main Loop</link>.
  16272. To interface smoothly with an arbitrary Asio async I/O operation, see <link
  16273. linkend="callbacks_asio">Then There&#8217;s <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link>.
  16274. </para>
  16275. <bridgehead renderas="sect3" id="fiber.rationale.h7">
  16276. <phrase id="fiber.rationale.tested_compilers"/><link linkend="fiber.rationale.tested_compilers">tested
  16277. compilers</link>
  16278. </bridgehead>
  16279. <para>
  16280. The library was tested with GCC-5.1.1, Clang-3.6.0 and MSVC-14.0 in c++11-mode.
  16281. </para>
  16282. <bridgehead renderas="sect3" id="fiber.rationale.h8">
  16283. <phrase id="fiber.rationale.supported_architectures"/><link linkend="fiber.rationale.supported_architectures">supported
  16284. architectures</link>
  16285. </bridgehead>
  16286. <para>
  16287. <emphasis role="bold">Boost.Fiber</emphasis> depends on <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>
  16288. - the list of supported architectures can be found <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/architectures.html">here</ulink>.
  16289. </para>
  16290. </section>
  16291. <section id="fiber.acknowledgements">
  16292. <title><link linkend="fiber.acknowledgements">Acknowledgments</link></title>
  16293. <para>
  16294. I'd like to thank Agustín Bergé, Eugene Yakubovich, Giovanni Piero Deretta
  16295. and especially Nat Goodspeed.
  16296. </para>
  16297. </section>
  16298. </library>