[Autogenerated] I've created a new project called Primes,
which is just another console application as we did before and
added the classic includes for Windows dot h and S t d i o dot h
and also added command line arguments here.
So we'll accept the number of threats we want to use using the command line.
So let's do something like this.
Let's assume we're going to have one thread and if we
have some parameter on the command line,
our eggs is greater than one.
Let's just assume that threads is going to be just a two y the integer
value of the string provided there in the second argument,
which is the first one after the executable name itself.
And of course we have to do some error checking here to
make sure that threads is a normal value,
which is at least one and so on.
I'm going to leave that out to save time because that's not really the point.
It's not a production level called just yet.
And so now that we have a bunch of threats,
we would like to perform the calculation.
So let's just call a function called calculate primes
And we'll give it the first number, let's go with three.
And the second number,
the last number is going to be something like maybe 20 million
and then also provide a number of threads.
And before we do that we want to uh to get the um, the start time.
So I'm going to use a simple function called Getty count
60 for just returns the number of milliseconds that have
elapsed since Windows started,
I'm going to just go ahead and call the same
function once the operation completes, then we can display the results.
So we have the total number of prime numbers that has been, has been calculated.
It's important to make sure that all the calculations at least give us the
same result and then the elapsed time that we have here,
which is in milliseconds, it's going to be uh end minus start.
So I'm just going to uh just cast that too to a single value because uh,
this is what we expect here to find and this is it from the main function here.
We just calling the color crimes function to perform the real work and then we
get the total number of primes that has been calculated and display how long
that thing took and of course the number itself.
So now we have to move forward and look at the color crimes function.
So here's call crimes.
We expect to get the first Number two use and then the second the last
number to use in the range and the number of threats.
So what do we need to do here first?
We need to chunk up our range of numbers into equal pieces as as much as we can.
So we can just use some division here.
So you have the number of actual numbers is two minus uh first.
Well let's just change the terminology here to make it more consistent.
So I'm going to be a last minus first plus one because you want to
include both of them and divided by threats.
So this is integer division,
which means the chunk is going to be an integral for sure.
Which means there might be some left over tale of numbers will
have to take care of in some way and we will,
the next thing to do is to run a loop.
We need to run a loop from zero to the number of threats that the number of
threats we have to create and then use the create thread function as before
in order to to create our threat or threats.
Really let them all kind of start executing and then
wait for all of them to complete.
So for that we have to maintain a list of handles.
Um so we need to have a handle array here somehow.
So here's one way of doing that.
We can just use simple functions such as malek from the c run
time to uh to allocate a bunch of handles.
So Malik always works in bite so we have to look at the size of handle
and times threats because number is is changing and also um we have to
cast here for the compiler to be happy.
That's one way of doing that.
And once we do that of course we have to call the free function and
at the end and then we'll have some total here,
we'll have to to calculate but we'll get to that very soon.
So that's one way of doing that.
If you're a C++ developer,
you might be doing something slightly more elegant if you wish.
You can use the memory header here and use something slightly different.
Let me just do that for simplicity by using something called make unique,
we can create a unique pointer to an array of handles with
the actual number of handles that we need.
And the advantage here is that at least one advantage is that
the destructor of unique pointer returned here is going to
free that memory automatically.
So the free call here is not needed.
In fact, it will it will be a buggy thing to to have it.
It will be a double free error.
So I'm going to use that.
But if you're a C developer, please feel free to use the classic way of working.
It's essentially the same thing that's going to be the handles.
And so now if I want to actually do something with with the code here,
I have to go and say handles.
I And here we're going to call the create create function and
create trade function has a bunch of parameters.
Most of them are not interesting.
The only really interesting piece.
Well two interesting pieces.
One of them is the function to run.
So let's call that uh I don't know count primes and then we need to
provide the thread with information as to the first and last numbers needs
to work with in order for the threat to do the right thing to work on the
range that belongs to that threat only.
So in this case we can't just pass a single number,
we have to pass at least two numbers the first and last for the range.
And that makes it harder to use a single integer but notice
that the parameter is the pointer to void,
which essentially means it can point to anything.
So to make it easier, we can create a structure called something like fred data.
And this is a very common practice when passing information to threats.
We can create a structure for as big as we like and then
simply pass it along to the threat by pointer.
So you can point to anything that we need.
So let's just create a few members here like first and last and
that would be only the first and last for a specific threat and
then we also have to return a result.
How many numbers have we found in that work for that particular threat.
So one way of doing that is to use the return value for the
threat as we did in the previous example because what we need
to return here is an integer,
which which goes very well with the return value of the threat but in a
generic case you might need to return something more complex.
So another common practice is to put the actual results in the same structure.
So some items here are are considered input to the thread
and some items are considered output.
So now that we have a definition for this structure,
we have to create a bunch of structures based on number of threats
really because each one should get its own copy.
We don't want to use a single copy because that would cause the same
data race problem we've seen in the previous clip.
So I'm going to use the same make unique idea here,
but you can use Malek if you wish or even the new operator
if you wish to do so it's all the same as as far as the
final functionality is concerned.
So I'm creating the same number of objects here based on number of threats.
So now we have to first prepare the appropriate data
structure and so before calling create thread,
first is going to be our first coming from the function plus I times the chunk.
So the first one is going to start with first.
The second thread will use firstplus chunk.
The third one will use firstplus twice chunk and so on.
So each one will go and start with the next chunk.
The last one is slightly trickier.
And because remember we have that tale of numbers we might have
there in order to um to have that calculated.
But someone by someone let's assume we're going to throw it at the last thread.
So if the eye here is threads -1, that would be the last thread.
Let's just give it the last number and that's it.
So it's going to be working slightly more.
And then if it's not the last thread,
what we need to do is just grab whatever is in first and
add chunk And -1 because we don't want to step over the
first item for the next spread, we don't want to do extra work,
which is in fact will give us incorrect result.
If we're just going to use the same number,
calculate the same number more than once and and this is it,
we don't have to do anything with count because it's
supposed to be an output here.
So I'm not going to specify anything there.
We can go ahead and provide the address of data I to the thread in question,
we have no specific creation flags.
Just let these threads just run by the way,
this is referred to as the ForkJoinPool kind of
algorithm where we fork a bunch of threats,
each one doing the same thing but on different data and then we need to
join meaning we have to wait until all of them are done.
So once we do that,
all the threads start running and now we have to wait here until
they're all done before we can harvest the results so you can
use the same way to repeal objects functions we've seen already
now a number of threats.
We know what number of threats is and just need to provide the handle array,
which in this case is provided by the member function.
Get from the unique pointer uh that we are using here.
If you just did a simple allocation using Mallow,
you will simply provide handles here and that it was it true
meanings that we want to wait for all the threats to complete and
infinite again means that we will to wait for as long as it takes
once we're done waiting, we can go ahead and harvest the results.
So let's grab a total here.
And the only thing we need to do here is just to move um
over all the threats that we have.
So again we have the same kind of loop here.
Just look at the count that was hopefully returned properly by
the threats or set properly by the threats.
Just going to uh use the data at index I and look at the count.
Each threat has accumulated and then we can return that total to the color.
There's another thing that here that is slightly missing and
that's closing the handles to all these threats.
So technically we actually should also close handles here.
So let's do that for uh well to be orderly and and not forget.
So we have the handles here.
Let's just close the handles.
There's a there's other there's another way and they're,
in fact, several ways to handle that anymore.
Um, I would say safe way.
So this closing is done automatically, but I'm not going to cover that.
That would be our main function and the color crimes function.
The only missing piece here is called crimes,
which we'll get to in the next clip.