 Hey, everyone. Welcome back. My name is Brian. And in this video, we're going to talk about Qt Concurrent. We're going to talk about what is it, why use it, and how to use it with some simple examples. Now, at a very high level, no pun intended, Qt Concurrent module provides high-level APIs. Now, notice some keywords here. It's a module, meaning we have to add it. But don't worry. It's ridiculously simple. And high level does not mean you lose power or functionality. Quite the opposite. It will make writing threads and working with threads ridiculously simple. And you don't have to deal with any of the low-level primitives such as mutexes, read write locks, weight conditions, semaphores, things that we haven't really touched on yet. But if you dive into threading a little too deep, you're going to run to them very, very quickly. So this is going to be a very high-level example, but it's going to just give you that power right at your fingertips, something that you can use today at the end of this video. Now, if you want a more in-depth review of threading, I do have a Qt 6 or Advanced with C++ out on Udemy. It's usually on sale. I also give it away for free in my VoidROM's Facebook group quite often. But if we just scroll down, there's a lot in this course. So forgive me. We scroll down all the way down to section 3 threading. You can see we really dive into the deep end on threading. But that's the beauty of Qt Concurrent is you don't have to know all that complexity. You can write high-performance, multi-threaded applications today. So let's dive in and take a look. So really, what is Qt Concurrent? Well, we're talking about concurrency here, meaning we want to be able to run multiple threads, synchronize them, and get values back and manipulate things using those threads. Concurrency is a very complex topic. And I probably just explained it very poorly. That's how complex it is. But Qt Concurrent is honestly just one of the most beautiful things that I have seen. And I'm not even joking. That being said, it has some functions in here. For example, map, which applies a function, notice the keyword here function to every item in a container. Meaning you could have like a function that says add 10, and it'll go through every item and say a list and modify it in place. That is awesome. And then there is the plural of that mapped ED mapped is like map, except it returns a new container. I mean, it creates an entirely new list and hands it back to you. And then there's reduced, which is like mapped, except for the modified results are reduced or folded into a single result, meaning it's going to make a computation and fold everything into one result. Then there's filter, which, you know, removes items and then filtered plural, which is, you know, pretty much the same except for a new container is generated and then filter reduced. Obviously, you can read the documentation for yourself. But we're going to micro focus on this little guy right here. Qt Concurrent run. This is going to be our buddy for this video. And we're going to work with what's called a future. If you don't understand the concept of a future, it means we're going to work with a value. But the value is not there yet, the value will exist in the future, but it doesn't exist yet. So this gets really confusing, but there's a lot of power to it. There's a future, a future iterator, a future watcher, a future synchronizer and a promise. And you can dive into the documentation if you want, we are going to cover some of these in this series. But at a high level understand what we can do with the future, we can monitor the status, we can wait for it to finish and we can even track its progress. Those are all advanced things. Pretty, pretty sweet. Alright, so let's look at this slide right here. Concurrent is a module. Now what do we mean by that when we flip back to the documentation and scroll up? First thing it says, the Qt Concurrent module, wait, what? What is a module? Well, Qt is well, big, it's massive. So it's not all one thing. It's a bunch of libraries. So you've got Qt Core, which we've been working with. But there's also like Network, Concurrent, Test, and there's others, of course, we're going to focus just on Concurrent. Now, because this is a module, we have to add this. And if you're still scratching your head going, I don't understand what a module is. A module is like an external library. It's a separate file altogether, be it a DLL, a library, or what is it called on Mac? Somebody tell me down in the comments, I think it's called a framework or something like that. I always forget what that's called. I just call it a library on Mac. But anyways, it's separate. It comes with Qt. You don't have to install anything extra, but we have to tell the compiler and the linker what's going on here. So we'll just have to add that and see, make it ridiculously simple. Don't stress about it. One question I'm always asked is, why even use Qt Concurrent? I mean, what am I really getting out of this? I've already learned how to use threads and I've learned how to use a thread pool and they're both awesome. So let's compare the three. We have what I call normal threading, which is basically you have a Qt application, you manually make some threads Q thread to be specific. And then you make some objects and you move those objects to those threads. You have to, of course, connect signals and slots to communicate with them. The problem is, well, I'm gonna be brutally honest with you, this sucks. This is mired in complexity, you have to manually manage these threads and the memory underneath. And you have to worry about things like what if dog is trying to communicate with bird, but bird doesn't exist anymore, bird got deleted. Bird flew into a ceiling fan or something. It's just not there anymore. You'll have those kind of issues, which will just completely measure application up. And on top of that, each time you create one of these threads, you're incurring a penalty in terms of CPU and RAM because threads have a real world cost associated with them. So we then moved on and learn the concept of a thread pool. I love thread pools. These are awesome. So you have pre existing threads that Qt has already created for us. And they live in a pool meaning it's just going to recycle these over and over again. Okay, this is very elegant. Because now you don't have that penalty in terms of CPU and RAM of creating new threads because they're already there. But you have to use what's called a Q a runnable, which is why I have an R here instead of a T. You have to use the runnable interface, and then inject that I should say send it to the thread pool and then wait for the thread pool to execute it. There's some complexity there, you have to understand Q runnable, you have to understand the thread pool, you have to use different techniques get information back, for example, signals and slots. It gets to be kind of cumbersome honestly, when you get used to it. So this is where Qt concurrent comes in. And current is part of Qt, but it's a module. So I've got it in this big green binary container here, which uses the thread pool under the hood. So what you're going to do is you're going to send something to concurrent, it's going to take the complexity of the runnable, and put it into the thread pool for you. And it's going to generate what's called a future. Now remember, a future means it's some sort of value we want to work with in the future, it doesn't yet exist. But the cool thing is you can actually hook up signals and slots to that future. So basically, if I can just take this and let's just bring to front, it looks more like this, let's call this concurrent. It really looks like this. Qt will send to concurrent, concurrent will hand you a future and you do whatever you need to do with it. You don't have to worry about any of the details under the hood. Now if I go ahead and send that to back, just understand what's happening under the hood is you have all of this beauty right here. You have a thread pool with multiple reusable threads and Qt handles all of that complexity for you. I love this. This is just simply amazing. Okay, I'm a huge fan of showing every single step. So I will try to go through this quickly because I don't want to waste your time. But we are going to open up Qt Creator, and I'm going to show you how to add the Qt concurrent module into your project. So we're going to make a new project. We're going to make a console application. And it's called this Qt 6 episode 24. Man, we are flying through these episodes. The big takeaway here is make sure you're using CMake as the build system. You can still use Q Make. But remember, they're not really developing that anymore. So they're going to favor CMake in the future. So we will as well. And this video is going to follow CMake. Now I'm not an expert at CMake. So bear with me on this. Kit selection as long as you use in Qt 6 or higher, you're good. Alright, what we have before us here is just a standard Qt CMake project. And I'm going to give it a good build just to make sure we have a happy little program. Once you see this little green bar, we got a solid build, meaning this thing is now runnable. Let's open up CMakeList.txt. Again, I am not a CMake expert, but this is ridiculously simple. They even have what you need in the documentation, but I will summarize for you. We need to modify these two fine packages and this target link libraries. So we're going to tell it to go out and find concurrent. And as long as you spell that correctly, everybody who watches my videos know I am a horrible speller. I actually have very terrible eyesight, but as long as you spell it correctly, it should work. Now what I like to do is take this where it says Qt version. I like to plop that in there as well. That way there's really no questions in CMake's mind on what we're trying to do here. But notice we're adding core and concurrent, core and concurrent, core and concurrent. This is just very simple and straightforward. Make sure you save this file and give it a good build. This may just take a microsecond longer to build, but the end result, you should get this right here. And if you don't, you can go into the compile output down here and figure out what happened. That being said, we saw the linker linked everything and it is just exit normally. So we are good to go. To give this a real test though, and I mean a real test, what we're going to do is I'm going to just plop in some includes through the old copy and paste. We're going to put in Q debug, Q random generator does exactly what it sounds like. It's just going to generate a random value for us. Our buddy Qthread and we're going to work with Qfuture. Remember, we want a value that's in the future and we want Qt concurrent. Notice this has got a t here. It's not Q concurrent. It's Qt concurrent because it's a module and you can highlight that hit F1. And of course, it gives you everything that I've just explained right here, how to add it in C make, how to add it in Q make. I absolutely love that. But once you have these in here, let's go ahead and give us a build. And this will prove to you about a shadow of doubt that it's linking correctly. And we've got a good build. If you don't get to this point, you'll have to go into your compile output and figure out what's going on. First thing we need to do here is, well, let's make some test functions. But before we do, I'm going to say, I'm going to plop in some code here so I can see what we're doing. So we're saying starting and finished. And then right here in between to do thread. Because we want to work with some awesome threading. Now the power of Qt concurrent is we don't have to work with those low level primitives. We can just say, hey, Qt concurrent, I want to thread something. Go do this. So I'm going to write a very complex function. Please pay attention. Let's say void test. I don't think I could write any more of that. But really what I'm doing here is I'm saying, okay, the simple little function, we're going to take this function and push it out to Qt concurrent. So I'm just going to grab him and let's go here. I'm going to demonstrate the non threaded version and then we're going to go ahead and thread this. So we're going to run this real quick. Alright, so notice how this is starting Q thread and it's all the same memory address. So if we really really want to what we can do here is say Q thread, current thread, set object name. Let's call this main thread. That way we can see without a shadow of a doubt what thread this thing's actually running on. Remember, we have not threaded yet. That's coming up really, really soon. Just bear with me here. Now that we've gotten to this point, we see that our function is running on the main thread. Let's go ahead and we're going to take this a little bit and modify it. So let's grab this. I want yet another function. So let's call this test random. Wow, if I could spell random that was embarrassing. It was a randomly bad joke. Anyways, let's go ahead and we're going to work with this. And we're gonna say Q thread, current thread, and we want to put this to sleep. So I'm gonna say MSleep. So whatever thread it's running on, we want to put it to sleep for one second. But then we want to go ahead and we want to return a value. Let's say return and we want Q a random generator global and bounded. And what bound is going to do is return a range. Notice it's wanting the highest. So we want to say in smacks added bonus, we're going to show you how to put a parameter in there. So all this really is going to do is it's going to say hey, we're running random on whatever the current thread is, we're gonna say current thread go to sleep for one whole second, which is an eternity in computer time. And then when you're done, go ahead and return a random number between whatever and whatever. Pretty simple. So let's dive in and see these things in action on a threaded application using Qt concurrent. Now that we've got our happy little functions here, test and test random, we're going to go ahead and work with these. So let's wipe this out. What we're going to do is we're going to say Qt concurrent. And then we're going to use run. Now you notice the signatures here. If you're coming from Qt five, be warned, these have flipped around. And when I mean that, I mean, the signatures have been flipped around. It used to be completely different. It used to be the arguments than the function, but now it's the function than the arguments. For this simplistic example, we're just going to say we're going to give it the function name of test. Notice what's happening here. Well, we're just saying Qt concurrent run this function. And it's just going to, well, you guessed it, run it. Go ahead and run this and see what happens. Okay, well, this just won't do. You see, it started, it finished, but then our test ran on a Q thread pool thread. That's the thread pool inside Q concurrent under pool. But notice the order started, finished, and then the test ran, meaning, well, our main thread is already done. And we want to actually stop and wait on this thing. So let's go ahead and work with what's called a future, which is what run is going to return. So let's go ahead and say Q future. And this is a template class. So we have to give it a type. In this case, it's going to be void because our function returns nothing. So we're telling Q future what to expect. And let's go ahead and call this f one. Now, what we can do is something like this. We can say f one dot and let's see, we want to do wait for finished. So it does exactly like it looks like it's going to do on the screen. We're saying, hey, concurrent, go run this function, give us a future, something that doesn't exist yet. And we're going to say, hey, our future, wait for that thread to finished. Let's go ahead and run this and see what it looks like now. Okay, that looks much better. So we have started and then we've done whatever we wanted to do. But we have this running on a thread pool inside Q concurrent. And then we can actually wait for it to be finished. And everything synchronized the way we wanted it. That is actually really cool. I love that. Okay, by now the power of Q concurrent should be pretty obvious. You can take any function, it doesn't even have to be designed for a thread. And really just say Q concurrent, go run that function in a thread pool and then do something with it. You can either wait for finished or return a value or whatever you want to do. This is just insanely powerful. So what we're going to do now is notch the difficulty up just a little bit. We're going to say Q concurrent, we're going to run test random. Notice test random has two different things. We're going to get a value in the future, doesn't exist yet. And we're going to feed it a value as a parameter. Okay, well, how do we do that? Let's go down here and say Q future, not Q feature translation, sorry Q future. There we go. And remember this is templated. So we have to get from the function what we're working with here. The return type is an int. So we're going to say this is going to be an integer. Notice the wording. It is going to be, not it is. Meaning the value does not exist yet but it will in the future. That's something you have to wrap your head around when working with futures. We're going to call this F2, you can name it fuzzy kitten or whatever you want. And we'll say Q concurrent. Of course we want run and this is where people coming from Qt 5 get very, very, very confused because they have flipped the arguments around. It used to be args then function, now it's functions and args. And I think in Qt 5, if memory serves, it was limited to five parameters. And you notice in Qt 6 what it's doing now. So let's go ahead and say we want to run this on the function name, test random, and let's give it a parameter. We want to say the max is 100 and we could do comma 200 whatever depending on how many parameters we have here. And there it is. So it's going to take our test random, load it into Qt concurrent, pass this value over to the function and then run this. Now here's the tricky bit. Remember how I said the future does not exist yet. It will exist and here's why. As this is running, this is going to run off to thread land out in Qt concurrent and it's going to do its thing. But in our code we're saying Q thread, current thread, sleep. So it's going to put that thread on the thread pool to sleep for one second and we can change that to longer. Then it will return that value and that one second in computer time is an eternity. So what we need to do is tell our program we need that value. So we're going to go ahead and say Q info and we want to just say random. So our random value is and let's go ahead and say f2 dot and we need some way of telling this we want this. Well we want the result and you notice how there are different ones. There's result, result at and this takes an index position and result count. That's right this can actually return multiple results. A little bit more complex than where we are now and you can get a list of the results if you're returning multiple. So this is extremely cool but we just want the one. So we're going to get the result of course this is templated so it's going to have our return type and we're going to say ta-da. We want this result. Now if we hit f1 returns the first result in the future if the result is not immediately available this function will block and wait. Burn that into your brain meaning we are now synchronizing these two threads and we're saying we are going to stop our program and wait for that thread to finish. Meaning we don't have to call wait for finished it's already in there. So let's go ahead and run this and see it in action. All right did you notice the pause we're going to run that again here in a second but let's step through this it's starting and then test is on our thread pooled random is on our thread pooled and then we have our random result and then finished. That went a little fast so what we're going to do here is we're going to kick this out to five seconds which is forever and ever in computer time. So five seconds let's go ahead and run this at the speed of my compiler there we go so starting test random and now it's sitting there waiting because that thread is asleep and we are waiting for that result. Finally it kicks back the random was 86 and then our beautiful finish back on our main thread. The major takeaway here is Qt concurrent is insanely powerful and yet very simple to work with. You can be a complete newbie and you can get this running today without even understanding how threads work. I hope you enjoyed this video. You can find the source code out on github.com. If you need additional help myself and thousands of other developers are hanging out in the void realms facebook group. This is a large group with lots of developers and we talk about everything technology related not just the technology that you just watched and if you want official training I do develop courses out on udemy.com. This is official classroom style training. If you go out there and the course you're looking for is just simply not there drop me a note I'm either working on it or I will actually develop it. I will put a link down below for all three of those and as always help me help you smash that like and subscribe button the more popular these videos become the more I'll create and publish out on youtube. Thank you for watching.