Você está na página 1de 3

ProjectHome Wiki Issues Source Administer

UpdatedMar30,2014byrazvan.coca
razvan.coca@gmail.com|Myfavorites|Profile|Signout
asiocodegen
Attempttoflattenstructureofboost::asioproactorcode
Searchprojects
Newpage Search Currentpages for Search Edit Delete
Rationale
Descriptionoftheproblemandsuggestedsolution
Introduction
Proactorbaseddesignsseemtoberesilienttofamiliarlayeredstructureofanapplication,forcingonetoinlineasyncopsinsidecompletion
handlers,justtohavethenextchunkofapplicationrun.
Details
Wenoticethatnestedfunctioncallsaremoreinacompileryard,andwetakeanexplicitactionofbuildingatreeofasyncservices,thenwalking
intheproperordertoruntheoperation/notifyupperlayers.
Thecontrolflowgoesasfollows:
composedasyncopcallsnextininorderasyncop.(preorderrunningismoreofashortcut)
thisallowsfortheoperationcomposedofAandBtorunAandB.
concurrentrunistrivialA()&&B().
cancelingeitherinsidecompletionhandleroftheotherisprettycommoninpractice
sequentialruninvolveschainingBinA'scompletionhandler.A()A_handler()runsB()
thishidesfromthecallertheactualcompositionoftheasyncop
Handlercallsnextinpostorderoperationnodetonotifyupperlayersoncompletion(ifchainedsequentially)
Handlercallsparenthandlertonotifyupperlayeronerror(thereforebreakingthechainonerror)
Gettingthislogicrightleavesuswithacomponentbased,composable,layeredstructure,thatcanbetestedindependentlyatanylevel.
Notes
secondlayercouldrunaprotocolstatemachine.anerrormapwouldbeinorderhere
upperlayerasyncopprovidesahandlercallabletobecalledbythelowerlayeruponcompletion
thereshouldbeasmanyhandlersasmanycomponentsmakeupupperlayeroperation
upperlayerkeepsapointertoitscomponents
thelifetimeofcomponentsisguaranteedbythelifetimeofthehandler
thelifetimeofhandlerisguaranteedbyboost::asiotobejustenoughtoinvokethehandler
Design
Foruniformityasyncopsarepackedtogetherwiththeirargumentsasincommandpattern.There'saweakptrpointingbacktotheactualnode
embeddedintotheresultingfunctor.Handlersarecomposedbymeansofawrapperthatwrapstogethertherunofupperandlowerlayer
handlers.boost::bindcoulddothisalso.Theresultingcompositionresultishookedintolowerlayeroperationascompletionhandler.
Thisisnottheabsolutelyminimaldesignfound,asimplecompose(juxtapositionofhandlers)andasimplebranch(conditionalcall)wouldbe
reallyminimal(possiblybetter).
// bind result works around a compiler shortcoming with variadic lambdas
// this wrapper should return a lambda that captured a weak this
template<typename Operation,typename... Args>
action_t wrap(boost::shared_ptr<Operation> self_,Args&& ...args)
{
boost::weak_ptr<Operation> weak_self_(self_);
action_t retval= std::bind([weak_self_](Args... args){
if(auto lself_=weak_self_.lock())
return lself_->exec(args...);
return false;
},
std::forward<Args>(args)...);
return retval;
};
// the extended if-then branch compose
// calls 2 handlers in sequence and execute an operation if no error occured.
// calling the second (upper) handler is skipped if error is found in ignore list.
// perfect forwarding is not desired, since this handler is tied with the lifetime of the operation
template<typename Handler1,typename Handler2,typename Action>
class branch_composed_handler_command
{
Handler1 handler1_;
Handler2 handler2_;
Action op_;
std::vector<int> skippable_list_;
public:
typedef void result_type ;
branch_composed_handler_command(Handler1& handler1,
Handler2& handler2,
Action& op,
std::vector<int>&& skippable_list):
handler1_(handler1),
handler2_(handler2),
op_(op),
skippable_list_ (std::move(skippable_list))
{
}
template<typename Arg0,typename ...Args>
void operator()(Arg0 const& ec,Args... args)
{
handler1_(ec,args...);
if(not_found(ec,skippable_list_))
{
handler2_(ec,args...);
}
if(!is_error(ec))
{
patterns::command::invoke(op_);
}
}
};
Withthesepiecesinplace,theexec(...args)methodofanycomposedoperationwouldhookthecomponentsinplaceandchaintheminproper
order.Theentireflowcontrolmovedinsidethisexec()method.Verylittleflowcontrolremainsinthecompletionhandlersofeachcomposed
operation:cancellingcompetingconcurrentcomponentsor/andcallinghigherlevelstatemachinestoadvancetheprotocolstates.
Achainofresponsibilitycanbeinvolvedtoprocesshigherprotocolaspectsandthatwouldcompletelyseparateprotocolcodefromnetworking
code.
Notes
Sofarithasn'tprovedusefultocompilethetreetoacompletesequentialrepresentation,thestructuredformlooksmoreclearinwrittencode.
Similarideascanbefoundin:
http://isocpp.org/blog/2013/10/patterns
http://stackoverflow.com/questions/18202398/isthereanywaytoasynchronouslywaitforafutureinboostasio
Examples
Example1
Amulticastclientwouldperformthefollowingactions:
setupatimertoabortontimeout.Thistimerattemptstoaccountforthenumberofmessagesexpectedtoarriveandstretchestimeout
accordingly.
chainupanactionmadeupofsendingarequestfollowedbyreceivingreplies
sendingarequestconsistsof:
preparingamessageandencryptingit
sendingtheencryptedmessage
receivingareplyconsistsof:
receivingamessagefromthewire
decryptingthemessage.possiblyreissuingareceive
Example2
Hint:YoucanuseWikiSyntax.
Amulticastserverwouldperformthefollowingactions:
chainupanactionmadeupofreceivingarequestfollowedbysendingreplies
receivingarequestconsistsof:
receivingamessagefromthewire
decryptingthemessage.
sendingareplyconsistsof:
preparingamessageandencryptingit
sendingtheencryptedmessage.
enqueuesendingofthenextreplyifsuchisthecase
Enteracomment:
Submit
TermsPrivacyProjectHostingHelp
PoweredbyGoogleProjectHosting

Você também pode gostar