Pages

Thursday, May 10, 2012

Basic Pel and Mel

Welcome » NERWous C

A Serial Producer / Consumer

This is a Producer / Consumer example written in standard C language:
main () {
     int c;
     while (c = Produce())
           Consume(c);
}
The main task works serially. It calls Produce to get a value to c, then calls Consume to consume it. The cycle repeats until there is no more products (with Produce returning 0).


A 3-Task NERW Producer / Consumer

Let's apply the NERW model to make the above code concurrent:
main () {
     <mel> int store;
     <pel> Producer (store);
     <pel> Consumer (store);
}
void Producer (<mel> int store) {
     int c;
     while ( c = Produce() )
         <?>store = c;

     <?>store = 0;
}
void Consumer (<mel> int store) {
     int c;
     while ( c = <?>store )
         Consume(c);
}
The task main creates a mel variable, store, as the communication channel between the Producer and Consumer. It then creates a task to run the Producer code via the pel construct, and immediately creates another task to run the Consumer code. The task main then waits for all the tasks it forks to be terminated.

The Producer task keeps producing until Produce returns 0. Every time it has a product, it will see if the mel store is available for it to deposit the product. By definition, the mel variable has one slot (we will see how to define a multi-slotted mel variable later). If a slower Consumer task has not consumed the previous product, the Producer will wait at the mel via the <?> construct. Once the deposit to the mel is successful, the Producer resumes its Produce chore. When it cannot Produce any more, it will deposit a 0 value to the mel to alert the Consumer task. The Producer task then terminates.

The Consumer task runs in parallel with the Producer task. The two synchronize at the mel variable store. If store is empty (due to a slower Producer) or is locked by the Producer while it deposits a new product, the Consumer task will wait at the <?> construct. Once it sees a 0-valued product, the Consumer task terminates.

With all tasks it forks terminated, the main task terminates itself. The application then exits.


A 2-Task NERW Producer / Consumer

Instead of pelling a task to run Consumer, the task main can run it by itself:
main () {
     <mel> int store;
     <pel> Producer (store);
     Consumer (store);
}
This will save some task resources.

No comments:

Post a Comment