Index: ossp-pkg/sio/sio.pod RCS File: /v/ossp/cvs/ossp-pkg/sio/sio.pod,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/sio/sio.pod,v' 2>/dev/null --- sio.pod 2002/11/08 10:36:35 1.2 +++ sio.pod 2002/11/08 11:03:13 1.3 @@ -405,7 +405,6 @@ char *c; } private_t; - static sio_rc_t XXX_init(sio_t *sio, void **up) { private_t *my; @@ -427,7 +426,6 @@ B and a corresponding cleanup function is called when the stage is detroyed with B. - static sio_rc_t XXX_cleanup(sio_t *sio, void *u) { private_t *my = (private_t *)u; @@ -444,7 +442,6 @@ parameters are passed through B to the configure function of the module. - static sio_rc_t XXX_configure(sio_t *sio, void *u, void *o, void *v) { private_t *my = (private_t *)u; @@ -538,6 +535,86 @@ assembly line and B schedules all stages attached to the output assembly line. +A full-duplex protocol however needs to mix input and output +operations. This can be done by telling the scheduler to +cross sides with the result code SIO_XSTREAM and by maintaining +a state machine that directs the scheduler back to the +originating track. + +Example: + + sio_rc_t XXX_openr(sio_t *sio, al_t *al, void *u) + { + private_t *my = (private_t *)u; + ... + /* cache reference to input assembly line */ + my->al_in = al; + my->state = INIT; + ... + } + sio_rc_t XXX_openw(sio_t *sio, al_t *al, void *u) + { + private_t *my = (private_t *)u; + ... + /* cache reference to output assembly line */ + my->al_out = al; + my->state = INIT; + ... + } + sio_rc_t XXX_input(sio_t *sio, al_t *al, void *u) + { + return XXX_protocol(sio, (private_t *)u, 0); + } + sio_rc_t XXX_output(sio_t *sio, al_t *al, void *u) + { + return XXX_protocol(sio, (private_t *)u, 1); + } + + + sio_rc_t XXX_protocol(sio_t *sio, private_t *my, int isoutput) + { + switch (my->state) { + case INIT: + my->isoutput = isoutput; + my->state = NEXT; + ... + /* protocol needs global assembly lines, + * we need to put aside any data */ + XXX_preserve_al(my); + + /* protocol starts with output */ + if (isoutput) { + + return SIO_LOOP; /* next state on this side */ + } else + return SIO_XSTREAM; /* next state on other side */ + + case NEXT: + .... + case INPUT: + al_append_bytes(my->al_in, ...); + ... + case OUTPUT: + al_append_bytes(my->al_out, ...); + ... + case LAST: + ... + my->state = DONE; + + /* restore global asembly lines */ + XXX_restore_output(my); + + if (isoutput != my->isoutput) + return SIO_XSTREAM; + else + return SIO_LOOP; + + case DONE: + ... + } + ... + } + =back