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.