yield equivalent in C/JavaScript?

Bengt Richter bokr at oz.net
Sun Jun 30 01:14:49 EDT 2002


On Sat, 29 Jun 2002 19:12:46 +0100, Robin Becker <robin at jessikat.fsnet.co.uk> wrote:

>Is there any way to do yielding easily in C? I have a bunch of programs
>which are normally connected together using unix pipes. I would like to
>merge them and the problem is then how to get them to communicate nicely
>using a single process.

But this involves switching back and forth between the processing contexts
writing to and reading from the pipes, so unless you use available threading,
pipe/stream buffering, etc., seems like you are going to reinvent a bunch of it
in one form or another. However, ...

If it's your code and you know what kind of chunks it naturally processes in,
then you could just rework the calling sequence so that you can do one sensible
chunk at a time, using a state parameter to switch to the appropriate internal
functionality (e.g., initialise() vs. fill_input_buffer vs. process_input_buffer).
The output from a chunk-producer can then be the input to a chunk-consumer,
calling both in a loop something like, e.g.,

#define FINI 0
#define INIT 1

int main(){
    int producer_state = INIT;
    int consumer_state = INIT;
    ...
    while(producer_state || consumer_state){   /* exit when both FINI */
        /* maybe feed producer_inbuf here if it doesn't do it*/
        producer_state = producer(producer_state, producer_inbuf, producer_outbuf);
        consumer_state = comsumer(consumer_state, producer_outbuf, consumer_outbuf);
        /* maybe dump consumer_outbuf here if it doesn't do it */
    ...
}
Note that the processes return a state value so they effectively control their internal
sequencing, like a state machine, so it's quite flexible.

Producer and consumer would work something like (just a sketch):

int producer(int state, char* inbuf, char* outbuf){
    switch(state){
    case INIT: {
        /* allocate processing chunk buffers*/
        initialize();
        return CHUNKIN;            /* returns like this yield control. Data goes via buffers */
        }
    case CHUNKIN: 
        add_to_chunk_buffer();     /* while inbuf data is available and chunk is incomplete */
        if( chunk_is_complete() ){
            return BLOCK_ON_OUPUT;
        } else {
            return CHUNKIN;
        }
    case BLOCK_ON_OUPUT: /* poll for space to process inbuf to outbuf */
        if( output_buffer_empty() ){
            return DOCHUNK;
        } else {
            return BLOCK_ON_OUTPUT;
        }
    case DOCHUNK: {
        /* sufficient input exists to do reasonable processing, and output space
           has been checked (assuming you know chunk size is less that buffer size), so do it*/
        ...
        if( end_detected_somehow()){
            return FINI;
        } else {
            return CHUNKIN; /*get more input*/
        }
    ...
}

Doing this conveniently depends on being able to do it at the outermost scope inside the processes,
so that you can return from and resume into the main top state dispatching loop. Otherwise you have
stack state that will need to be saved and restored, and then you're re-inventing stuff again.

Hm, this doesn't look like Python ;-p

>
>the typical process currently looks like
>
>        initialise();
>        while((c=getc(stdin))>=0){
>                process(c);
>                putc(c,stdout);
>                }
>
Is process(c) just eavesdropping on a verbatim copy stream?

>so if the inputs are reasonable I could just run each to completion
>before proceeding with the next by replacing the file streams with
>memory ones. That could get messy if the inputs are large.
>
Can you get the processes to do limited-size chunks at a time, so producer
and consumer can alternate, and you can control that reasonably?

>Is there a neat way to simulate the yield idea? In C I can just about
>consider doing some longjump madness, but that wont wash in the other
>possible environment which has JavaScript for implementation.
You really mean JavaScript, not Java?

Regards,
Bengt Richter



More information about the Python-list mailing list