We're now going to look at adding to
and removing things from the Queues.
The next slide shows
the beginning of the put_on_queue routine.
It takes a ticket and an integer.
The ticket of course refers to
the Queue to which you're going to be adding something,
and the integer is what you're going to be adding.
The first thing you'll see
there is simply the check to be sure
that the ticket that was passed in
actually corresponds to an index in the Queue array,
rather than the array of Queues.
If not, we immediately return the air and
noticed that read ref already put
the error message into the qe_errbuf.
If it is valid we now have
the index which is in Queue curve,
and we go onto the next step which is
to make sure that the Queue is not full.
If it's full we give an error message and we give
some information about how
many elements you can have it in there,
and return an appropriate error code.
If it's not full then we go ahead and
add things to the Queue in the usual way,
and notice that the head count and
count are not check for consistency here.
That's because they were checked for consistency in
read ref when the token was changed into the index,
and had they been inconsistent there,
you would never reach this routine
because read ref would return an error.
Removing an element from
a Queue is a little bit different.
Notice we don't pass an address of an integer variable.
So, in other words we're not going to return it directly.
We're going to return it through as
a return value not through the parameter list.
Again here we simply convert the ticket to an index,
and then on the next slide we simply
check to be sure that the Queue's not empty.
If it is empty we give an error.
If it's not empty we just grab
the first element advance the head one, two.
Indicate that the new head is one back,
and then we simply return the element.
Now, notice the "if" and the "else" both of returns.
So we should never get past that "if and else."
This is an example of can't happen.
I can't conceive of any way this could be changed.
But you never know someone may come
along and change something internally.
So, one of the returns only
occurs under certain conditions.
So, what we do here is at
the bottom we have a message that basically says
"Boy something's really wrong,"
and then we returned it internal inconsistency.
So, if someone monkeys with
the two return statements in such a way that one of them,
that neither will be executed and forgets
to add something else or
deal with the failure in some way,
deal with the lack of executing one of them in some way.
We've now got a fail-safe they'll fall into
this air buff and
then the return and you'll get an internal inconsistency.
Now, again why didn't we pass in a pointer to
an integer variable and return the value that way?
Because as it is now if the head of
the Queue contains a negative number,
when it returns that could be mistaken as an error.
Well, the reason is as I said before how do you
verify that something is
actually pointing to an integer variable?
You can verify it's not null.
But the address may be
a function pointer or something else.
So, it's better to avoid that problem
entirely and avoid passing pointers whenever possible.
But this does leave the question
of how do you disambiguate
a negative value from
the Queue with a negative value indicating an error?
And to do that, we
have to talk about how to call the removing function.
Now, whenever an error occurs
something is always putting qe_errbuf.
Always. We can use that if no error occurs,
and what's in there doesn't change,
then what's in there won't change.
So, we can identify that and say nothing.
No the negative number is really on the Queue.
Or from the Queue. But if
it changes then we say that's an error.
The problem is we don't know what qe_errbuf may contain
before we call remove or take off.
So, what we do is we clobber
the first byte of
qe_errbuf and put a known value in there.
I use null. You can use whatever you like.
Null is nice because
an error message will never contain that.
We then call takeoff Q.
The next thing we do is check whether or not
it could be an error that's ISERROR.
If it's non-negative, you immediately go to the else.
If it is negative,
then you have to check to see whether or not
errbuf was changed whether
or not something was written in the errbuf.
If not, then you go to the else.
But if there was in the first byte will
definitely be a non-null byte.
Then it's an error code and you give the error message.
So, that's how you do the disambiguation.
For you Linux hackers that's exactly how you do
the disambiguation for the system call LC.