Charles.Forsyth20071227-123052dd9a418 years agoHistory
156 lines · 3.9 KB · Text
RawDownload
.TH STYXFLUSH 2.SH NAMEstyxflush \- handler for styx flush protocol.SH SYNOPSIS.EXinclude "sys.m";include "styx.m";include "styxflush.m"; styxflush := load Styxflush Styxflush->PATH;init: fn();tmsg: fn(m: ref Styx->Tmsg,	flushc: chan of (int, chan of int),	reply: chan of ref Styx->Rmsg): (int, ref Styx->Rmsg);rmsg: fn(m: ref Styx->Rmsg): int;Einterrupted: con "interrupted";.EE.SH DESCRIPTIONGetting the semantics of the Styx.IR flush (5)protocol correct when handling requests concurrentlyis surprisingly hard to do..I Styxflushis designed to help get it right. It deals with Styxmessages for a single styx session \- if a server needs todeal with multiple sessions, then multiple instances of.I styxflushshould be loaded. It assumes there is a loop in a central processwhich both reads T-messages and sends their R-message replies..I Styxflushhandles the flushing of requests that are being runoutside the central process..PP.B Initmust be called before anything else in.I styxflushto intialise its internal data structures..PPWhen a T-message request arrives that will be dealt with concurrently,.B tmsg(\fIm\fP,\ \fIflushc\fP,\ \fIreply\fP)should be called to inform.I styxflushof the new request..I Mgives the T-message;.I flushcgives a channel that will be used if the request is flushed (see below),and.I replyshould hold an unbuffered channel that can be used to send a replyto the central loop..I Flushcwill usually be a fresh channel for each request, but severalrequests may share the same.IR flushcif, for instance, one process is managing several requests..B Tmsgreturns a tuple(\fIhandled,\ rm\fP),where.I handledis non-zero if.I styxflushhas dealt with the request itself. If it has, thenthe caller must not handle the request; itmust send .I rmas a reply if it is not nil..PP.B Rmsgshould be called when a reply message arrives at the central process(the same process that has called.BR tmsg ).It returns non-zero if the reply message should actually besent to the client - otherwise it should be discarded..SS "Flush Channel".I Styxflushnotifies a request that it has been flushed by sending a tuple,say.IR "" ( tag ,\  rc )on its flush channel..I Taggives the tag of the message that has been flushed,and.I rcis a channel that should be replied on when therequest has been dealt with. There is no requirementthat a request read on its flush channel - if it does not,then the replies to any flushes of that request will be delayeduntil the request is replied to.If it does read a flush request, however, it must replyto the original request before sending on.IR rc .If it has succeeded in aborting the request, it shouldsend an.IR error (5)R-message with the message.B interrupted(defined as.BR Einterrupted );otherwise it should send itsreply as usual..SH SOURCE.B /appl/lib/styxflush.b.SH EXAMPLEThis is a skeleton of a prototypical structure of a programthat uses.IR styxflush ..EXreplyc: chan of ref Rmsg;centralloop(tm: chan of ref Tmsg, fd: ref Sys->FD){	replyc = chan of Rmsg;	for(;;)alt{	m := <-tm =>		if(m == nil || tagof m == tagof Tmsg.Readerror){			cleanup();		# kill outstanding processes, etc.			return;		}		flushc := chan of (int, chan of int);		(handled, rm) := styxflush->tmsg(m, flushc, replyc);		if(!handled)			spawn request(m, flushc);		else if(rm != nil)			sendreply(rm);	rm := <- replyc =>		if(styxflush->rmsg(rm))			sendreply(rm);	}}		sendreply(fd: ref Sys->FD, rm: ref Rmsg){	d := rm.pack();	sys->write(fd, d, len d);} request(tm: ref Tmsg, flushc: chan of (int, chan of int)){	pick m := tm {	Open =>		replyc <-= ref Rmsg.Open(m.tag, ...);	Read =>		[...]		alt{		x := <-readc =>			# read from data produced on readc			replyc <-= ref Rmsg.Read(m.tag, ...);		(nil, rc) := <-flushc =>			# read request has been flushed.			replyc <-= ref Rmsg.Error(m.tag, Einterrupted);			rc <-= 1;		}	etc ...	}}