So guys, now we will going to implement the last part of our solution and we will going to implement
this API philosopher, get access, both spoons, right?
So the implementation of this API has to abide by this following logic represented by this flowchart,
we will going to provide the implementation of this API exactly as per this flowchart.
Right.
And you can see this flow chart has been designed by keeping the constraints in mind which our problem
statement has presented to us.
You can see that to start with, our philosopher will try to grab an axis on the left spoon.
So the very first thing that we will do is that we will check whether the left spoon is available.
If the left spoon is not available, then our philosopher thread must wait on the condition variable
of the left spoon.
Right.
And in case if the left spoon is available, then our philosopher thread will update the state of the
spoon in a way which reflects that the left spoon is now allocated to the philosopher right, and it
is after the left spoon has been successfully granted to the philosopher.
Our philosopher will now check if the right spoon is available or not.
And as per the problem statement, if the right spoon is not available, our philosopher who has successfully
gained an access on the left spoon, will roll back and give up the access on the left spoon as well.
Right.
And in case if the right spoon is available, then our philosopher will end up with an access to both
the spoons.
And this function must return.
True.
Which indicates that the philosopher has been successfully granted an access to both of his spoons.
Right.
So this flowchart is pretty much simple and straightforward.
And this flowchart exactly depicts the problem statement as well as the constraints that we have imposed
on our problem.
So let us start with the implementation of this flowchart in the function philosopher.
Get access both spoons.
Right.
This function returns true or false depending on whether the philosopher has been granted access to
both of his spoons successfully or not.
So guys, to start with, the very first thing that we need to do is to check whether the left spoon
is available or not.
Right.
If it is available, then we will grab an access to the spoon.
If it is not available, then our philosopher thread must wait on the condition variable.
So let us implement this logic.
So to start with, I already have a pointer to the left spoon of the philosopher.
So what I will going to do is that I will lock the mutex of the left spoon, right, because I'm going
to inspect the state of the left spoon whether the spoon is available or not.
The thread must lock the mutex of the spoon so that at the time when the thread is checking or inspecting
the state of the resource, the state of the resource must not be changed by any other philosopher in
the program.
Right?
So once I have successfully gained a lock on the mutex of the left, spoon or philosopher thread can
now deploy a predicate check on using while condition.
Right.
This is something that we have been doing in a standard way now, not that our philosopher function
is trying to get an access on a resource.
It means that our philosopher function is now behaving as a consumer thread.
So it means that in order to consume a resource, we need to deploy the steps from S1 to S5.
Right?
So these are nothing, but these are the steps number S1, which involves checking of the predicate
condition.
Here I am checking whether the left spoon is available or not.
Right.
So this while condition will become true if the left spoon is already being used by some other philosopher.
Right.
If that is true, then my current philosopher will going to block on the condition variable of the left
spoon.
Right.
So here.
Now, in this case, we will going to implement exactly the steps which a typical consumer thread implements.
Right?
So we will proceed beyond line number 139 only when the left spoon is available to be used by the philosopher.
Right.
This, while condition will become false only when the left spoon becomes available.
Right.
In case if our philosopher thread gets blocked on this condition variable, our philosopher thread would
wake up only when it would receive a signal from other philosopher thread.
In that case, our philosopher thread will again check the predicate condition to decide whether our
philosopher thread can grant an access on the left spoon or not.
So from line number 130 to line number 139, this is a standard predicate check condition which a typical
consumer thread implements.
Right?
So we will be executing beyond line number 139 when the left spoon is available to be used by the philosopher.
Right.
So now the second thing that I need to do is to grab the left spoon, right, because it is available.
So I will update the state of the left spoon such that the left spoon now belongs to our philosopher,
right?
And now that I am done with the left spoon, now it's the time to unlock the mutex of the left spoon.
Right.
So at this point of time in the code, the left spoon has been successfully grabbed by my philosopher.
And now, as per the flowchart, I will come to the right spoon.
I will check whether the right spoon is available or not.
So going further in this function, what I will going to do is that our philosopher will going to check
whether the right spoon is available or not.
So again, my philosopher thread has to lock the mutex of the right spoon before inspecting the state
of the right spoon.
Right.
Always remember that in multithreading or in thread synchronization, whenever your thread has to inspect
the state of the resource, the resource must be locked by a checking thread.
Right.
So now, going forward, my philosopher thread will check whether the right spoon is available or not.
Now if the right spoon is not being used by any other philosopher, it means that is used.
Flag of the right spoon would be false.
So it means that this right spoon is available if this if condition becomes true.
Right.
So in that case my philosopher thread would grab an access on the right spoon.
Right?
So you can see here my philosopher thread is updating the state of the right spoon in a way that it
reflects that the right spoon belongs to my philosopher.
Right?
And we are done here.
So it's time to unlock the mutex of the right spoon.
And at this point of time in the code, both the left and the right spoon has been successfully grabbed
by my philosopher.
So this function should return.
True, right?
We are done in this function.
But what will happen if the right spoon is not available?
Right?
That is, it is being used by some other philosopher.
So as per this flowchart, we will going to implement this box.
That is the last box.
That is give up the left spoon as well.
If the right spoon is not available.
So going further in this code, you can see that I am checking that if the right spoon is being used
by some other philosopher.
Right.
So this elseif condition says that the right spoon is being used and by some other philosopher that
is the owner of this.
Right?
Spoon is not equal to my philosopher.
So I would enter inside the inner if condition, only when the right spoon is being used by some other
philosopher.
So in that case, my philosopher thread has to give up an access on the left spoon as well.
So again, lock the mutex of the left spoon because my philosopher thread has to update the state of
the left spoon so that the left spoon do not belong to my philosopher anymore.
Right.
So you can see that I'm updating the state of the left spoon again and unlock the mutex of the left.
Spoon.
Right.
And since right spoon is not available to my philosopher, so unlock the mutex of the right spoon as
well and return false.
I'm done.
So you can see that this piece of code simply make my philosopher to roll back.
Right?
Because the right spoon was not available and it was being used by some other philosopher.
My current philosopher intentionally loses the access to the left spoon as well and return false from
this function.
And finally, the last case that is we will hit this else block only when the right spoon is being used
by our current philosopher only, Right?
So most probably we will not going to ever hit this else.
Block But there is no harm in this case.
We will simply unlock the mutex of the right spoon.
And the right spoon is already being used by our philosopher.
So simply return true, right?
So most probably we will not going to hit the lines number 191 to line number 194.
But for the sake of completeness of the program covering all the scenarios, let us complete the else
block as well.
Right.
So this completes the implementation of this function and the line number 197 and 98 is actually a dead
code.
We will never going to hit the line number 197, because in every branch of this code we have returned.
Right?
So you can see that the implementation of this function exactly reflects this flowchart.
We have done nothing extra and nothing less, right?
Now, in the next lecture video, we will compile and we will see how to test whether our dining philosophers
problem solution is working fine or not, and how to test whether every philosopher in this problem
is getting an equal treatment.
That is, it should not happen that one philosopher is starving while the rest of the philosophers are
enjoying the cake.