WEBVTT

00:06.780 --> 00:11.970
So, guys, now, next, let us discuss what are the common APIs that we will going to write in order

00:11.970 --> 00:13.260
to solve our problem.

00:13.470 --> 00:18.480
So now I will going to discuss what are the functions you will going to write in the file assignment

00:18.480 --> 00:20.850
dining philosophers, right.

00:21.090 --> 00:25.180
So to begin with, you can see on the screen the three APIs.

00:25.200 --> 00:31.830
Now, these three APIs are very common APIs and they have nothing to do with the thread synchronization.

00:31.830 --> 00:33.630
In each of these APIs.

00:33.630 --> 00:39.510
You don't have to use any mutex or condition variables and you just have to provide the plain implementation

00:39.510 --> 00:40.810
of these APIs.

00:40.830 --> 00:46.980
So you can see as the first API says, that philosopher get right spoon, it simply means that this

00:47.010 --> 00:52.380
API returns a pointer to the right spoon of the philosopher, which is passed as an argument.

00:52.590 --> 00:58.920
So it simply means, for example, suppose this API is being invoked on the philosopher one.

00:59.280 --> 01:03.150
So this API must return a pointer to the spoon as p zero.

01:03.420 --> 01:04.290
Right?

01:04.320 --> 01:12.520
Similarly, if this API is being invoked on a philosopher zero then it must return a pointer to the

01:12.520 --> 01:13.870
spoon as before.

01:13.870 --> 01:14.710
Right.

01:14.920 --> 01:21.190
Similarly, you have the second API which returns a pointer to the left spoon of the philosopher, which

01:21.190 --> 01:22.660
is passed as an argument.

01:22.780 --> 01:23.560
Right.

01:23.560 --> 01:29.680
So the implementation of these APIs is very simple and easy and we will discuss their implementation

01:29.680 --> 01:33.280
quickly when we will be discussing the complete solution.

01:33.430 --> 01:40.570
The third API is the philosopher eat, which should represent that the philosopher has gotten access

01:40.570 --> 01:50.740
to both of his spoon and this API must block or sleep for one second because as per our constraint,

01:50.770 --> 01:54.520
the philosopher once get an access to both of his spoons.

01:54.520 --> 01:56.890
He enjoyed the cake for one second.

01:57.040 --> 01:57.820
Right.

01:58.030 --> 02:05.290
So enjoying the cake for one second is equal to making this function sleep for one second.

02:05.560 --> 02:06.420
Right.

02:06.430 --> 02:13.930
And the code logic to implement the solution of dining philosopher problem would go in these two APIs.

02:13.960 --> 02:19.840
That is philosopher released both the spoons and philosopher get access both the spoons.

02:19.840 --> 02:20.560
Right?

02:20.560 --> 02:24.040
So the core solution will go in these two APIs.

02:24.070 --> 02:28.930
We will going to discuss the implementation of these two APIs in a step by step manner.

02:28.930 --> 02:33.510
But first, let us set up our assignment dining philosopher dot C file.

02:33.520 --> 02:38.080
So let us set up our skeleton structure of our solution file.

02:39.660 --> 02:45.210
So guys on the screen, you can see that I've opened the file assignment dining philosophers.

02:45.570 --> 02:48.970
And this is the file which represents our assignment file.

02:48.990 --> 02:53.640
It is this file in which you need to provide the solution to dining philosophers problem.

02:54.400 --> 02:59.860
So as you can see, as per our diagram, we have five philosopher, for example.

02:59.860 --> 03:02.970
So five philosopher means you have five spoons.

03:02.980 --> 03:09.790
So it simply means that you can always take some constant value and let us initialize it to five, right?

03:10.030 --> 03:14.290
And now we have to take five philosophers and five spoons.

03:14.290 --> 03:21.430
So you can just take static arrays, which represents the collection of philosopher objects and spoon

03:21.430 --> 03:22.330
objects.

03:22.330 --> 03:23.050
Right?

03:24.940 --> 03:27.340
And now to begin with, the main function.

03:27.340 --> 03:34.310
In the main function, we will going to initialize the philosopher objects and spoon objects, right?

03:34.330 --> 03:40.330
So what we will going to do is that we will going to create a loop.

03:40.570 --> 03:45.370
And in this loop, first of all, we will going to initialize all the spoons.

03:45.670 --> 03:51.490
So you can see that I'm assigning spoon IDs.

03:51.490 --> 03:54.840
And initially to begin with, all the spoons are available.

03:54.850 --> 03:56.050
Therefore is used.

03:56.050 --> 03:57.640
Flag is set to false.

03:57.670 --> 04:00.370
There is no philosopher who is using the spoon.

04:00.400 --> 04:08.430
I therefore it is set to null and initialize the condition variable and the mutex object of the spoons.

04:08.440 --> 04:09.280
Right.

04:09.370 --> 04:15.220
So you can see that every spoon is given a ID starting from zero to n minus one.

04:16.150 --> 04:17.470
As simple as that.

04:17.710 --> 04:22.630
So in this block of code, we have done the initialization of spawn objects.

04:22.660 --> 04:27.010
Now, next we will do the initialization of philosopher objects.

04:27.040 --> 04:30.170
Now, remember, philosophers are nothing, but they are threads.

04:30.190 --> 04:36.670
It is for this reason that I will going to create all the philosopher threads in the detached mode.

04:36.700 --> 04:37.560
Right?

04:37.570 --> 04:41.080
Because eventually they will going to run in an infinite loop.

04:41.080 --> 04:41.620
So.

04:41.620 --> 04:48.850
So those philosopher threads have no use case to join any other thread and hence it is better to create

04:48.850 --> 04:51.190
philosopher threads as detached threads.

04:51.460 --> 04:57.160
So again, I will create a loop and I'm initializing each philosopher object.

04:57.370 --> 05:05.290
Every philosopher is given an id I right, and each count of every philosopher will going to be zero.

05:05.290 --> 05:08.800
And remember that philosophers are nothing but they are threads.

05:08.800 --> 05:15.550
So it is for this reason that the thread which represents a philosopher is being triggered in this line

05:15.650 --> 05:17.660
that is in line number 64.

05:17.660 --> 05:18.350
Right?

05:18.350 --> 05:24.050
And this completes the initialization of spoons and philosophers, right?

05:24.080 --> 05:27.560
Now here you can see that I have passed a philosopher function.

05:27.560 --> 05:30.770
So it is in this philosopher functions.

05:30.770 --> 05:36.530
So it is this philosopher function where we will going to start the implementation of code logic of

05:36.530 --> 05:37.970
our solution.

05:37.970 --> 05:38.600
Right?

05:38.630 --> 05:42.800
The starting point of our solution is this function that is philosopher function.

05:42.800 --> 05:47.840
And remember, this philosopher function will be executed by each philosopher, right?

05:47.840 --> 05:55.130
If you have five philosophers, all five philosophers will going to execute philosopher function concurrently.

05:55.130 --> 05:55.820
Right?

05:57.630 --> 06:03.900
And remember, while writing a solution, you have to write a generic solution.

06:03.900 --> 06:05.310
Meaning that.

06:06.200 --> 06:10.340
You cannot write any piece of code which is specific to some philosopher.

06:10.370 --> 06:11.870
Say philosopher number three.

06:11.990 --> 06:12.640
Right?

06:12.650 --> 06:18.740
It is just not allowed because this philosopher function will be executed by all the philosophers and

06:18.740 --> 06:22.880
you would never know how many philosophers your program can have.

06:22.910 --> 06:23.720
Right?

06:24.880 --> 06:30.850
So the solution that we were going to implement would be generic, and it should work for any number

06:30.850 --> 06:33.400
of philosophers or any number of spoons.

06:33.430 --> 06:37.990
Needless to say, the number of philosophers has to be equal to the number of spoons.

06:40.000 --> 06:41.450
And now, guys.

06:41.470 --> 06:44.320
Next, we will going to implement these supporting APIs.

06:44.320 --> 06:46.960
That is the first three APIs, right?

06:49.130 --> 06:54.530
So to start with, let us implement the function philosopher get right spoon right.

06:54.530 --> 06:58.940
And the implementation of this function is fairly very simple and easy.

06:58.970 --> 07:05.300
This function usually returns the spoon number I minus one for the philosopher I right.

07:07.380 --> 07:13.200
And of course, you need to test out the boundary condition that if the philosopher ID is zero, then

07:13.200 --> 07:17.700
you need to return the spoon number as before as per our diagram.

07:17.700 --> 07:18.420
Right.

07:20.590 --> 07:26.530
Similarly, going forward, you can also provide the implementation of the function philosopher get

07:26.530 --> 07:30.940
slapped spoon and the implementation of this API is even simpler.

07:30.970 --> 07:31.810
Right.

07:31.810 --> 07:36.760
For philosopher K, the left spoon will be K right.

07:36.760 --> 07:42.310
So just return the pointer to the left spoon of the philosopher which is passed as an argument.

07:42.580 --> 07:47.440
And the next API that we will going to implement is the philosopher eat API.

07:47.650 --> 07:48.460
Right.

07:48.520 --> 07:54.610
The invocation of this API represents that this particular philosopher has gotten access to both of

07:54.610 --> 08:00.730
his spoons and this philosopher would going to enjoy the delicious cake for one second.

08:00.760 --> 08:03.070
So you can see that in this API.

08:03.100 --> 08:08.920
First of all, what we will going to do is to simply check that this philosopher, which is passed as

08:08.920 --> 08:14.620
an argument, must have gotten access to both of his spoon, Right.

08:14.770 --> 08:21.980
So you can see that I am getting a pointer to the left spoon and the pointer to the right spoon of this

08:21.980 --> 08:26.720
philosopher using the APIs which we have written above, right?

08:26.720 --> 08:33.680
And once we get a pointer to both of his spoon, now we will assume that both of these spoon have been

08:33.680 --> 08:35.990
already assigned to this philosopher.

08:35.990 --> 08:36.710
Right?

08:36.740 --> 08:40.130
That is why we have invoked the function philosopher Eat.

08:40.400 --> 08:47.090
So it simply means that we will going to check the state of the data structure to verify that left and

08:47.090 --> 08:51.080
right spoon have really been assigned to the philosopher.

08:51.260 --> 08:59.060
So for that you can simply check that the owner of the spoon is the philosopher himself, which is passed

08:59.060 --> 09:00.860
as an argument, right?

09:00.860 --> 09:07.610
And if it is not the case, then you just have to crash your application because you have invoked the

09:07.610 --> 09:08.480
function.

09:08.510 --> 09:13.160
Assuming that the philosopher has been assigned both of his spoons.

09:13.160 --> 09:18.100
But here the state of the data structure is indicating something else, right?

09:18.110 --> 09:25.250
So crashing the program intentionally helps to identify the problems at an early stage and fix them.

09:25.640 --> 09:32.720
And going forward, the is used flag of the left and the right spoon must be set to true right because

09:32.720 --> 09:36.530
the philosopher has already gotten access to both of these spoons.

09:36.620 --> 09:44.360
And finally, when all the conditions which state that the philosopher has rightfully gotten access

09:44.360 --> 09:51.800
to both of his left and right spoons, then in that case we can increment the eat count variable of

09:51.800 --> 09:56.630
the philosopher, meaning that philosopher is now enjoying the delicious cake.

09:56.630 --> 10:04.010
And remember that we had a constraint that philosopher must eat a cake for exactly one second.

10:04.010 --> 10:04.700
Right?

10:04.700 --> 10:08.780
So let the philosopher enjoy his turn of eating for one second.

10:08.780 --> 10:14.180
And this is how we are satisfying our one of the constraint of our problem statement.

10:14.390 --> 10:15.170
Right?

10:15.290 --> 10:21.200
So you can see that these three functions are very simple and plain functions and has nothing to do

10:21.200 --> 10:22.910
with the thread synchronization.

10:23.150 --> 10:31.040
Now that we have these utility functions ready, now we can actually start implementing the main or

10:31.040 --> 10:35.390
core logic of our dining philosopher problem solution, Right?

10:36.090 --> 10:43.140
So in this program we need to provide the implementation of the function philosopher release both spoons,

10:43.470 --> 10:44.280
right?

10:44.280 --> 10:48.750
And we need to provide the implementation to the function philosopher.

10:48.780 --> 10:52.020
Get access, both spoons, right?

10:52.500 --> 10:57.630
So the main solution of this problem statement would be implemented in these two functions.

10:57.630 --> 11:02.520
Plus we need to implement the starting logic in the philosopher function.

11:02.520 --> 11:08.130
Remember, philosopher function is a function which would execute in the context of the philosopher

11:08.130 --> 11:09.630
threads, right?

11:09.630 --> 11:15.780
So the starting point of our solution is the philosopher function, which in turn will make use of these

11:15.780 --> 11:19.470
two functions in order to implement the solution.

11:19.470 --> 11:26.520
So this is the file which is now ready for you and you should start provide the implementation of philosopher

11:26.520 --> 11:31.830
function philosopher get access both spoons and philosopher release both spoons.

11:31.860 --> 11:35.880
Other than that, you don't have to make any other code changes in this file.
