WEBVTT

00:05.410 --> 00:11.170
So, guys, now in this lecture video, we will going to implement producer consumer problem statement.

00:11.320 --> 00:17.440
So all the codes that is related to producer consumer can be found in this code directory path and the

00:17.440 --> 00:23.860
file which represents an assignment into which we will going to write a code is this file that is assignment

00:23.860 --> 00:25.870
producer consumer on Q dot C.

00:26.080 --> 00:26.920
Right?

00:26.920 --> 00:32.920
So since the producer consumer are the threads which needs to act on a common resource, that particular

00:32.920 --> 00:33.850
resource is nothing.

00:33.850 --> 00:36.280
But we have taken that as a queue.

00:36.490 --> 00:42.490
So the queue data structure is implemented by these source file that is Q, dot C and Q dot H.

00:42.670 --> 00:48.850
We will going to use these files in the assignment and compile Dot as such is a shell script that compiles

00:48.850 --> 00:51.970
your entire assignment and create an executable exe.

00:52.390 --> 00:56.290
You simply need to run this executable in order to test your code.

00:56.320 --> 00:57.100
Right?

00:59.090 --> 01:03.500
So this is the assignment file into which we will going to write a code.

01:03.680 --> 01:07.790
So now let us understand the problem statement in little bit detail.

01:07.820 --> 01:14.120
So what we will going to do is that in our program we will have our resource which is represented by

01:14.120 --> 01:14.840
a data structure.

01:14.840 --> 01:22.100
Q Right, so this is the common resource which needs to be accessed by producer and consumer threads.

01:22.460 --> 01:26.600
We will going to create a program in which there will be two consumer threads.

01:26.630 --> 01:31.310
The name of the two consumer thread is Tc1 and Tc2, right?

01:31.310 --> 01:37.220
And as the name suggests, these are consumer threads, meaning that both these threads has the objective

01:37.220 --> 01:40.850
to remove an element from the queue until the queue is empty.

01:40.880 --> 01:41.750
Right.

01:42.020 --> 01:47.780
Then in our program we will going to launch two more threads which are called producer threads.

01:47.780 --> 01:51.110
So the name of the threads is tp1 and tp2.

01:51.110 --> 01:57.260
And the objective of the producer threads is to create an element and push it into the queue until the

01:57.260 --> 01:58.550
queue is full.

01:58.550 --> 01:59.420
Right?

01:59.540 --> 02:04.640
So you can see the job of the producer and consumer threads is exactly opposite to each other.

02:04.940 --> 02:11.240
Then queue is a common data structure which is being acted upon by consumer and producer threads.

02:11.240 --> 02:15.590
Therefore queue has condition variable and a mutex.

02:15.590 --> 02:16.340
Right.

02:19.040 --> 02:25.550
We already know that mutex is always a property of the resource that is being shared by the threads

02:25.550 --> 02:30.140
and condition variable we have taken in this case as a property of the queue.

02:30.170 --> 02:31.010
Right.

02:32.930 --> 02:40.430
All the threads which are competing to get an access over the shared resource queue will be blocked

02:40.460 --> 02:43.810
on this condition variable if the queue is not available.

02:43.820 --> 02:44.630
Right.

02:45.350 --> 02:51.920
So if you happen to take a look at the implementation of this queue, I will show you that while you

02:51.920 --> 02:52.940
open the file queue.

02:52.970 --> 02:54.260
Dot h.

02:55.860 --> 03:00.060
You will see that this is the data structure which represents the queue.

03:00.060 --> 03:03.650
And this data structure has a mutex and a condition variable.

03:03.660 --> 03:04.440
Right.

03:06.480 --> 03:12.450
And note that the default size of the queue is five, meaning that the maximum size of the queue cannot

03:12.450 --> 03:13.890
grow beyond five.

03:13.920 --> 03:19.860
We will going to discuss how to make use of this queue library in our program in order to implement

03:19.860 --> 03:22.170
our producer consumer problem statement.

03:22.560 --> 03:28.950
So now we know that in our program we need to launch two consumer threads and two producer threads and

03:28.950 --> 03:35.370
we have a common data source which is queue, which all the four threads would compete to get an access,

03:35.400 --> 03:36.030
right?

03:36.060 --> 03:41.160
These slides, which represents the problem statement have been attached in the resource section so

03:41.160 --> 03:45.570
that you can refer to the problem statement and attempt the solution by your own.

03:46.100 --> 03:49.590
Now let us discuss what exactly the problem statement is.

03:49.610 --> 03:55.040
So we will going to write a program which launches four threads to consumer threads and two producer

03:55.040 --> 03:55.820
threads.

03:56.060 --> 03:59.570
And you may create these threads in the joinable mode.

03:59.600 --> 04:06.210
Right now, all these four threads act on a shared resource which is nothing but a queue of integers.

04:06.230 --> 04:10.550
So you need to create a queue which store the integers as an element.

04:10.700 --> 04:15.080
Producer thread produce a random integer and add it to a queue.

04:15.110 --> 04:18.350
Whereas consumer threads remove an integer from the queue.

04:18.380 --> 04:19.160
Right.

04:19.160 --> 04:21.710
And the maximum size of the queue is five.

04:21.740 --> 04:23.360
This we have already discussed.

04:24.230 --> 04:28.840
So this is the overview of the problem statement that we will going to resolve.

04:28.850 --> 04:35.360
And also our problem statement has certain constraints which you need to implement or you need to respect.

04:35.780 --> 04:40.220
So while writing a solution, you need to implement the following constraints as well.

04:40.310 --> 04:45.810
The first constraint says that when produce a thread, produce an element and add it to the queue.

04:45.840 --> 04:50.580
The producer thread does not release the queue until the queue is full.

04:50.610 --> 04:55.320
That is, producer thread releases the queue only when the queue is full.

04:55.350 --> 04:56.220
Right.

04:56.250 --> 05:01.440
So producer thread keep on adding element to the queue until the queue is full.

05:02.100 --> 05:07.110
Once the queue is full only then the producer thread actually releases the queue.

05:07.350 --> 05:13.110
Similarly, when consumer thread consume an element from the queue, it consumes the entire queue and

05:13.110 --> 05:16.050
do not release the queue until the queue is empty.

05:16.050 --> 05:16.890
Right.

05:16.920 --> 05:23.250
And the point number three says that consumer thread signals the producer thread when the queue is exhausted

05:23.250 --> 05:27.780
and producer thread signals the consumer thread when the queue is full.

05:27.810 --> 05:33.300
So you can see that there is bidirectional communication between consumer threads and producer threads.

05:33.330 --> 05:39.960
The consumer thread signals the producers, whereas producer thread signals the consumers right.

05:41.810 --> 05:45.590
And while implementing the solution, please use the following guideline.

05:45.590 --> 05:49.970
Use as many printers as possible so that you can debug the program easily.

05:49.970 --> 05:56.390
The program, which involves multithreading are hard to debug using debugging tools such as GDB or et

05:56.390 --> 05:57.110
cetera.

05:57.350 --> 06:03.860
Print f should be extensively used in your program so that if your program encounter a deadlock like

06:03.860 --> 06:10.700
situation, you can very well analyze the logs or the sequence of events taking place from the print

06:10.700 --> 06:11.420
f output.

06:11.420 --> 06:15.170
And you would figure it out that what exactly the problem is.

06:15.170 --> 06:15.890
Right?

06:16.250 --> 06:21.830
And going further, since in our program we need to make use of the data structure.

06:21.830 --> 06:29.300
So Q dot is the header file and this header file will give you the access to the following APIs, right?

06:29.330 --> 06:36.020
You can see on the right hand side that you can make use of the Q by using the following APIs in this

06:36.020 --> 06:36.530
way.

06:36.530 --> 06:42.900
So this is the example usage regarding how you can make use of the Q in your program.

06:42.900 --> 06:49.260
So for example, if you want to create a new Q, you can simply use the API init Q and it will give

06:49.260 --> 06:52.350
you a pointer to the Q which has been initialized.

06:52.440 --> 06:59.240
Similarly, if you need to check whether the Q is empty, you can use this API and in order to enqueue

06:59.250 --> 07:04.380
an integer element into the Q, you can simply use the Q API, right?

07:04.380 --> 07:09.120
So in this example we are simply queuing up the element five in the queue.

07:09.300 --> 07:13.200
And in case if you remove an element from the queue, you can use an API.

07:13.410 --> 07:19.050
Q Right, it will remove an element from the queue and it will give you an integer value.

07:20.440 --> 07:25.870
Similarly, if you need to find how many elements are present in the queue, you can use this queue

07:25.930 --> 07:27.160
underscore count.

07:27.190 --> 07:28.000
Right.

07:28.120 --> 07:34.420
And this is another is queue full which will tell you whether your queue is full or not.

07:34.450 --> 07:39.820
So while writing the solution which implements producer consumer problem statement that we have just

07:39.820 --> 07:45.580
discussed, you need to make use of these APIs on the queue data structure, right?

07:46.120 --> 07:52.690
So now in the next lecture video, let us set up our homework problem to begin with and then we will

07:52.690 --> 07:58.420
discuss how to write producer and consumer algorithms in order to implement the producer consumer problem

07:58.420 --> 08:04.180
statement that we have discussed and also respect all the constraints that we have discussed.
