Pages

Tuesday, April 12, 2016

Mel Readonly Access

Welcome » NERWous C » Mel
  1. Readonly Statement
  2. Readonly Abbreviation
  3. Readonly Queue
  4. Sequence Property
  5. Readonly On Read
  6. Readonly Mels
  7. Readonly Access to Exclusive Zones


Readonly Statement

In the previous section, we have an Inspector task that changes the sequence of produced items for consumption. In this section, let's introduce a non-intrusive Monitor task that preserves the sequence and the value at the mel variable.
main () {
    <mel> int store;
    <!> Producer (store);
    <!> Consumer (store);
    <!> Monitor (store);
}
void Producer (<mel> int store) {
    int n = random();
    while ( --n ) {
        try {
            <?>store = Produce();
        }
        catch ( store<NOREADERS || CLOSED> ) break;
    }
    printf ("Done Producing");
}
void Consumer (<mel> int store) {
    int n = random();
    while ( --n ) {
        try { 
            Consume (<?>store);
        }
        catch ( store<NOWRITERS || CLOSED> ) break;
    }   
    printf ("Done Consuming");
}   
void Monitor(<mel> int store) {
    try {
       <? mode=readonly timeout>store;
        if ( !Examine (store<value>) ) {   // examine it
            printf ("Stop the line -- value [%d] does not pass inspection", store<value>));
            <close>store;
            return;
        }
        printf ("Value [%d] is good for consumption", store<value>);
        <resume>;
    }
    catch ( store<NOWRITERS> ) return;
    catch ( store<TIMEOUT> ) <resume>;

    printf ("Done Monitoring");
}
We have a Producer that Produces a random number of items before ending. Likewise, we have a Consumer that Consumes a random number of items before ending. We also have a new task, Monitor, that runs until there is no more produced item to Examine.

The Monitor task accesses the mel store via a readonly operation, by adding the attribute mode with the value readonly to the wait operator ?. When Monitor comes to the mel and does not see a new item, it will wait. Whenever there is a new item, it will get its value. While the usual read operation gets the value and removes the item from the mel, the readonly operation gets the value but leaves the item back in the mel variable. Other readonly operations can subsequently get that value, until a read operation comes along and removes the item from the mel variable.

Because of the potential wait, the mel readonly statement supports the timeout attribute. (In the above example, Monitor catches the TIMEOUT exception but does nothing special except retries again.) However the mel readonly statement does not support the priority attribute because a readonly wait is already at the highest priority, as explained later in the Readonly Queue section.


Readonly Abbreviation

The readonly operation can be popular in a NERWous C program since not all tasks are reader tasks like our consumer tasks which remove a read value from the mel variable. For example the result of a parallel computation is a mel variable to allow the parallel tasks to build up that result. Once generated, this result will be accessed by downstream tasks. These tasks should access the result mel variable as readonly operations to allow the value to remain at the mel variable for all.

Like any other code>mode attributes, the mode=readonly attribute can be shortened with the removal of the mode keyword. Thus:
<? mode=readonly timeout>store;
can be written as:
<?readonly timeout>store;


Readonly Queue

When a readonly task comes to a mel and finds it empty, it will wait at the readonly queue. There is only one such a queue for each mel, unlike the many priority read queues used by the read operations. When a writer task deposits a new item into the mel, all tasks waiting in the readonly queue will get this item's value, remove themselves from the queue and get off the readonly wait. Once all the tasks waiting in the readonly queue have been served, the task at the top of the highest priority read queue can take away the item from the mel.

When a readonly task comes to the mel, and finds an item in the mel, how does it know if this item is new or stale? A stale item is one that it has accessed before, and is still available in the mel because no reader has come to retrieve it yet. This is where the mel sequence number comes into play. When a mel is first created, its sequence number is 0. When a writer deposits a new item into a mel, it increases that sequence number. In NERWous C, the data type of the mel sequence number is long long. Once the maximum of this huge number is attained, the sequence number is rewound to 0.

When a readonly task comes to a mel, it carries along the sequence number of its last read/readonly item. This value is 0 if the task has not accessed the item before. If this cached sequence number is different from the actual sequence number of the mel, the mel is new as far as the readonly task is concerned. The readonly task then simply takes a snapshot of the mel value and is done with the readonly operation.

If the two sequence numbers are the same, the mel is deemed stale, and the readonly task will put itself into the readonly queue of the mel, and waits. It first waits for a reader to come along to take away the stale mel. Then it looks a new mel item. A new mel item can come from the next item already in the mel buffer. If the mel buffer is empty, the readonly task has to wait for a writer to deposit a new item into the mel buffer.

If the mel is buffered, newly unread items may already be present in the buffer while the top item of the buffer (i.e. the item to be read) is stale. However these items are not available to the readonly tasks. If they detect the top item to be stale, they still have to get into the readonly queue until a reader task removes the top item off the mel buffer and exposes the next item. The NERW concurrency model does not allow readonly tasks to read ahead.

The same readonly queue is used on two occasions - first when the mel is empty, and secondly when the mel has an item. In the first case, all the readonly tasks that come for the mel will automatically go into the readonly queue. In the second case, only the readonly tasks that find the mel to be stale, go into the readonly queue. For both cases, all the waiting readonly tasks can only leave the readonly queue when there is a new item deposited into the mel.


Sequence Property

As mentioned above, when a writer task deposits an item into a mel, it increases the mel sequence number. A consumer tasks that gets the value of a mel (either via a read, readonly, or a no-wait snapshot operation), will retrieve this sequence number along with the mel value. This sequence number is cached locally in the mel property, sequence.

Let's modify Monitor to display the read values and their sequence numbers:
void Monitor(<mel> int store) {
    try {
        <?readonly timeout>store;
        printf ("Read value [%d] with sequence [%lld]\n", store<value>, store<sequence>);
        if ( !Examine (store<value>) ) {   // examine it
            printf ("Stop the line -- value [%d] does not pass inspection", store<value>);
            <close>store;
            return;
        }
        printf ("Value [%d] is good for consumption", store<value>);
        <resume>;
      }
      catch ( store<NOWRITERS> ) return;
      catch ( store<TIMEOUT> ) <resume>;
    }
    printf ("Done Monitoring");
}
Since the mel sequence number is a long long, the locally cached sequence property is also a long long.


Readonly On Read

As we already know, the tasks waiting on the readonly queue will access a newly deposited value before all reader tasks even those in the highest-priority queue. However it does not mean that a readonly task will see all the mel values. Let's take the Producer/Monitor/Consumer example above. The task Monitor can possibly miss Produce'd values that the task Consumer does not, even though the readonly queue used by Monitor is processed before any priority queue that Consumer does a read on. This will happen if the Monitor iteration is slower than the Consumer iteration. In this case, by the time Monitor goes to the mel store for another readonly, the Consumer may have time to access the mel store to read out one or multiple mel values, and Monitor is none of the wiser.

A second thing we already know is that a readonly task depends on a reader task in order to proceed, due to the case of a stale value. Even if a writer task has slotted a new value in the mel buffer, if there is no reader task to remove the existing stale value at the top of the buffer, the readonly task is stuck waiting.


Readonly Mels

A mel can be declared as a readonly mel so that all accesses to it are readonly:
<mel mode=readonly>int store;
The mode attribute can be omitted:
<mel readonly>int store;
Only readonly accesses are permitted to a readonly mel. Thus a <?>store is a syntax error since it is using a normal read operation. On the other hand, < mode=readonly>store and <?readonly>store are valid.

Since all read accesses to a readonly mel is readonly, there is no reader to take away a stale value. This responsibility is now assumed by a writer. When a writer deposits a new value to a readonly mel, all the tasks waiting in the readonly queue will get that value and can get off their wait. Contrast this to a readonly access to a regular mel: a writer can only unblock readonly tasks if the latter are waiting on an empty mel, but not on a stale mel.

Readonly mels are the default mode for returned values of a pel task to be explored later.


Readonly Access to Exclusive Zones

So far we have seen mel variables being blocked just enough for a read or write operation to complete. Later, we will be acquainted to exclusive zones where a mel variable can be held up for a longer period of time to allow the blocking task to run though its logic without other mel access interference. While a reader task has to wait for the exclusive zone to be available, a readonly task can get to the value of the mel variable at any time if this value is not stale. Readonly access to exclusive zones is described as part of the exclusive zone discussion.


Previous Next Top

No comments:

Post a Comment