Welcome
» NERWous C
In the previous Producer/Consumer example, we have two Producers vying for the same mel. If they come to the mel at the same time, the run-time environment will allow one Producer to enter the mel, while the other waits at the
Let's modify the previous Producer/Consumer example by introducing a second Consumer:
Unlike the temporaneous mel exception
With the existing
In NERWous C, there is a better way to write
We can pass an array of many Consumers to
In the previous Producer/Consumer example, we have two Producers vying for the same mel. If they come to the mel at the same time, the run-time environment will allow one Producer to enter the mel, while the other waits at the
?
. If the Consumer is slow to empty the mel, the mel can get full, and the Producers have to wait for room to be made available again on the mel. Instead of waiting, the Producers have the option to check for this no-room condition through the mel exception NOROOM
.
Let's modify the previous Producer/Consumer example by introducing a second Consumer:
main() {
pel Consumer() c1;
pel Consumer() c2;
pel Producer1(c1, c2);
pel Producer2(c1);
}
void Producer1 (pel Consumer c1, pel Consumer c2) {
int product;
for (int i=0; i<10; ++i) {
product = produce();
try {
?c1!val = product;
}
catch (c1!val!NOROOM) {
?c2!val = product;
}
}
}
void Producer2 (pel Consumer c) {
for (int i=0; i<70; ++i)
?c!val = produce();
}
void Consumer (mel int val) {
try {
while ( 1 )
consume (?val);
}
catch (val!NOIN) {
printf ("No more producers to me");
}
}
The first Producer makes use of both Consumers. The second Producer uses only the first Consumer. The first Consumer's input mel val
can be slow to drain because of its serving of two Producers. If things buffer up and this mel has no room, the first Producer detects this condition via the NOROOM
mel exception and switch to the second Consumer. On the other hand, the second Producer sticks with its Consumer and opts for waiting at the ?c!val
until the mel buffer is freed up for it to deposit the product.
Unlike the temporaneous mel exception
NOOUT
, the NOROOM
exception is immediate when the Producer checks the mel variable at ?c!val
. On the other hand, the NOOUT
exception depends on the run-time environment to monitor all consumers of the mel variable and raise that exception if after a configurable amount of time it has not detected any consumption.
With the existing
NOROOM
exception, there is no need for Producer1
to add the NOOUT
checking to its mel communication between itself and Consumer1
. However we can enhance the 2nd Producer so that it will not wait forever if its Consumer1
partner has terminated, and there is no consumer for its product:
void Producer2 (pel Consumer c) {
for (int i=0; i<70; ++i) {
try {
?c!val = produce();
}
catch (?c!val!NOOUT) {
print ("My consumer has gone away. I go home too.");
break; // out of for loop
}
}
}
It is worth repeating that NOROOM
is different from NOOUT
. If Producer2
were using NOROOM
, it would exit at the first detection of the buffer-full condition at the mel variable ?c!val
. With the use of NOOUT
, Producer2
will wait for a configurable amount of time for the Consumer
to catch up on its consumption and clear out the mel buffer val
In NERWous C, there is a better way to write
Producer1
so that it will keep trying between Consumer1
and Consumer2
if their mel ports are in the NOROOM
mode (i.e. full), until either one port can accept the product or until the NOOUT
conditions have been detected at both ports (i.e. both Consumers have terminated):
void Producer1 (pel Consumer c1, pel Consumer c2) {
int product;
for (int i=0; i<10; ++i) {
product = produce();
try {
(?c1!val NOROOM ?c2!val)<somebody_take_me> = product;
}
catch (?c1!val!NOOUT) {
printf ("Consumer1 has terminated. I continue with Consumer2 only.");
nobreak; // continue waiting with c2 only
}
catch (?c2!val!NOOUT) {
printf ("Consumer2 has terminated; I continue with Consumer1 only.");
nobreak; // continue waiting with c1 only
}
catch (somebody_take_me!NOOUT) {
printf ("Both consumers have terminated. I go home too.");
break; // out of for loop
}
}
}
Here, Producer1
checks ?c1!val
first. If this mel has NOROOM
, it checks ?c2!val
. If this mel also has NOROOM
, it goes back to check ?c1!val
. This continuous checking is programmatically tagged
with the tag somebody_take_me
. This tagged checking continues until either Consumer mel takes in the product, or a NOOUT
condition has been raised on both Consumer mels.
We can pass an array of many Consumers to
Producer1
, too:
void Producer1 (pel Consumer c[]) {
int product;
for (int i=0; i<10; ++i) {
product = produce();
try {
(?c[]!val NOROOM)<somebody_take_me> = product;
}
catch (somebody_take_me!NOOUT) {
printf ("All consumers have terminated. I go home too.");
break; // out of for loop
}
}
}
In the above example, the Producer1
will try all consumers in the array c
. If the first consumer is full (i.e. NOROOM
), then Producer1
will try the next consumer in the array. If none of the consumers in the array are available, it will loop back and check the first one again. This busy check will continue forever until one consumer can take the product (and Producer1
can go on and produce another product
until 10
are produced), or the exception NOOUT
is raised when the running system detects that all the consumers in the array have terminated. If some consumers have terminated and some consumers are still active, then the NOOUT
exception is not raised.
No comments:
Post a Comment