 Hey everybody, this is Brian and I am back from summer vacation. I had a great summer, but it's simply time to start recording again. So this video is going to pick up where the series left off, but we're going to jump right into the scary deep end. We're going to talk about the redding. So this video is an introduction to threading. If you already understand the concept of threads and threading, use the buffer bar below to skip ahead to the section you want to see. We're going to cover what is a thread, why do we use threads, how Qt uses threads, and we're going to wrap this up with a very simple threaded example. I have to stress it's going to be a simple threaded example because threading can get very complex and the next few videos we're going to dive into that complexity. Let's take a look. So what are threads? Well, prepare to be very, very confused because this is computer science 101. If you are a newbie computer person or a newbie programmer, you may have some questions. We're going to turn to Wikipedia and we're going to look at the simple thread in terms of computing. You can read this very straightforward, at least to me it is, document, but you're still going to be very confused. So fortunately they have this graphic and well, this is also confusing, but let's break it down here. So you have a program. This is what we as developers create, the actual program. Now this is the binary that exists on the hard drive. When the operating system runs your program, it creates an instance of it in memory. So what does that really mean? Well, your program can be created and run in memory multiple times. We call those processes. So each process is a copy of your program. Now each process or each copy of your program can have multiple threads and this is really what we're talking about in these videos. What is a thread? Well, you notice these numbers. Number one, two, three, four. Well, you have instructions one, two, three, four. When you see the term instruction, think of that as like lines or blocks of code. So for example, you could run instruction one, instruction two, three and four on different threads one, two, three and four. Now these don't line up one for one. That's the confusing part. Just because you have instruction two doesn't mean it's on thread number two. The operating system really determines where things run. So to rewind, you have a program. It is on the disk. It gets loaded into a RAM as a process. That process will talk to the scheduler usually in the form of creating what's called a thread class, which talks to the actual operating system. And what the scheduler here does is it says, oh, you want to run these threads, these threads line up with some instructions, I'll figure out the best place for them in the CPU and run them for you. Meaning we have very little control over this part right here. All we do as a developer is we create the instructions, decide how we want them threaded and then ask the scheduler, pretty please, thread them for us. Now, if all of that seemed overly simple, there is a lot of complexity to threads that we're going to talk about in future videos. You're going to hear some very confusing terms like semaphores, mutexes, mutex lockers, things like that. Don't worry about those yet. We're going to cover those in future videos. At its core, really what we're talking about is taking a block of code, running it through the scheduler and putting it on the CPU. Now, modern CPUs are very, very powerful. I'll give you an example. I'm going to look at system monitor, I'm on Linux, but virtually every operating system has something like this. I have one physical CPU and that CPU has eight cores. So I can have eight instructions running simultaneously. Actually I can have many more than that based off how the scheduler works. Remember, this happens very, very quickly. So even if I only had just this one CPU, the scheduler will say run instruction one, stop it and run instruction two, but it does it so fast it appears they're running at the same time. This is incredibly powerful and honestly, the more cores you have and the better performing OS you have, the faster your program is going to run. One question you may be asking is why even use threads? This sounds super, super complicated and it can be, to be brutally honest, why even bother with it? Well, the answer is very simple. A process with two threads of execution running on one processor. This little image here is beautiful because you have a process in instance of your application with multiple threads running at the same time, meaning you can do more than one thing at a time. You ever have to do that like in life at school or at a job where you have to do multiple things at once like type and talk on the phone? That's exactly what we're telling our process to do. Let's take a look here. We have a physical CPU and we have some instruction, a piece of code here. Now, typically what we've done and let's just make a couple of these is we've got different instructions, instruction one, two and three. Now, these are just blocks of code or functions, whatever you want. They would just go in order, one, then two, then three, very, very slow, right? Because two's not going to run until one's done and three's not going to run until one and two are done, so it takes time to get there. Yeah, no, we don't have time for any of that nonsense. We're in threading lands, so what we're going to do here is we're going to thread these and here is our CPU. Now inside, I shouldn't say inside, but also including this is the scheduler, so we're not talking directly to the hardware, we're talking to the operating system, so let's just say OS slash CPU. And then we're going to say, hey, let's put it here, we're going to run this one, we're going to run this one, and we're going to run this one. Pretty cool, right? So now we can run multiple things at the same time. Now, if you remember, you may have more than one CPU. For example, I have one physical CPU, but I have eight cores. Well, let's just take this and what we're going to do here is just represent a core. Let's shrink him down. This is where the complexity gets a little bit weird, so the operating system is going to figure out the best place for these. We don't really get to say, you're not going to say run this on core too, it just simply doesn't work that way. You just say, I want to run some instructions, I want them multi-threaded, the operating system figures out where they need to go, and it puts it on, you guessed it, the right area here. So this is a very high level of what we're talking about. You can do multiple things at once. The operating system is powerful enough to talk to the underlying hardware and figure out how to do those multiple things at once. The end result is your program can be multiple times faster, and I am not even joking. I have seen programs, once you switch to a threaded model, will go from, say, one to two minutes down to a second, or they'll go from an hour down to maybe ten seconds. I mean, literally you can have that kind of speed boost if you design your applications appropriately. As you might have guessed, this can get very confusing very quickly. CUTE, however, makes this very, very simple. So we're going to take this, and we're going to modify it a bit. We have multiple instructions inside of our application, and then I'm going to take this, and we're going to say, this is CUTE, and what CUTE does is it allows us to take all of this code, put it right through CUTE, and we're going to use a class called CUTE THREAD. Now CUTE THREAD is a bit mysterious. What does CUTE THREAD really do? Well, you can take different classes like CAT, DOG, BIRD, that have all sets of instructions in them, and say, I want to move this to the THREAD. So we're going to take him, and we're going to grab him, and say, move that right to a THREAD, and then the THREAD, and talk to the operating system and the scheduler. Now, unfortunately, the confusing bit is you're going to think, I am going to move all these two, but when you do that, they all run on the same THREAD, so you don't want to add them all to the same THREAD. Typically, what you would do is have multiple THREADs, something like this, so you'd say, I want CAT and BIRD to be on different THREADs than the DOG, and then they would, of course, under the hood, talk to the operating system and the CPU. So this is really what we're going to be doing, and then this example that we're about to do, we're just going to take one class and move it to a THREAD, and then run it in a multi-threaded fashion, so you can see how it actually flows. Just bear in mind that if you don't do it like this, like if you were to just get rid of these, do something like this, what's going to happen? Well, let's say you have a CAT doing, well, what CATs do, and dogs doing what dogs do, and birds doing what they do, they're all going to run one at a time on the same THREAD, so you want to avoid this type of situation here. Let's take a look at a very simple example. Again, I have to stress, this is the simplest example I could probably think of, so I'm going to start this from scratch, but in future videos, we're all going to start with a program that's open and ready. So I'm going to make a console application, and let's call this cute six episode 21. Next, when you see, make is the build system, and whatever kit you have, I realize there's a newer one out, I haven't installed it yet, doesn't really matter. There's not a lot of changes. All right, let's go ahead and there'll be a little bit of copy and paste in this video, but I'm going to plop in some notes real quick. All right, so we're going to create a QTHREAD, we're going to move an instance of a class to it, and it cannot have a parent. It's very important that if you remember anything from this video, when you move a class to a thread, it cannot have a parent. There's a reason for that. All right, so let's go ahead and right click, I'm going to add new, I'm going to make a class, I'm going to call this the worker. This is going to be a Q object, so it has signals and slots and all that goodness baked right into it. Next, and finish. Now we need to, of course, update CMake, and because I'm coming back from summer vacation, I'm a bit rusty on the typing, so forgive any misspellings. All right, now we've got our worker here. We're going to do two things right up front. We're going to put in QTHREAD and QTOBUG, and QTHREAD is built right into QtCore, so don't worry about that, but what QTHREAD does is it provides a platform-independent way to manage threads. Yes, I am aware that C++, specific versions of it, have this baked into it, but we're talking about Qt and how Qt does threading. You can use the standard library thread model if you want, but obviously in this video, we're going to cover the Qt threads. So we've got our worker, and we're going to do two very specific things here. We're going to make a deconstructor and a public slot called run. The premise here is when we move our object to the thread, it's not running yet, we have to tell it to run, but the worker won't magically know when the thread starts, so we're going to connect these two with signals and slots. When the thread starts, it's going to call our run slot, so let's flesh these out real quick. So inside the worker, this becomes very, very simple, and I'm going to just copy and paste a little snippet here. So we're going to say Q info, and we're going to print out this current object, and we're saying constructed, and then this little bit of magic here, Q thread, and we want to get the current thread, so we're just going to print that out. Under the hood, the current thread is just simply a Q thread, which is also a Q object, so it has signals and slots baked right into it. And we're going to say deconstructed. Now, what we're going to do later on is we're going to name that thread, so you can see on the screen the difference between the main thread and the worker thread that we're about to create. Now, in this run function, when this thread actually runs, we're going to do something a little different. I'm going to say four and I, and let's just go up to 10, and we're going to go ahead and increment I, very simple little loop here. Now I'm going to just grab this to save a smidge of typing, and we're going to say this working, and then we want the integer here. So let's go ahead and say, we're going to convert that I into a Q string, and then we're going to print out the current thread. We can, if we want to get rid of that right there. So very simply, just going to say working, and then the number that we're on, and then our current thread that we're running on. Notice I said of the current thread that we're running on, because we could run this on any thread we felt like. Now I want to slow things down because computers are much faster than we are. I'm going to say Q thread, I'm going to say current thread, MS sleep. Now what this is going to do is tell it to put the thread to sleep or stop executing for a certain number of milliseconds. And I'm going to say 500, which is half of a second. So it's still fairly snappy. Now I'm going to put something in here right now, but it's not going to make sense probably till towards the end of the video. Let's say this, delete later. What this is going to do is delete this object out of memory, but again, it's not going to make sense just yet. Let's flip over to our main here. Now we could, if we wanted to, create our worker and run it on the main thread. And let's go ahead and demonstrate that. We're going to include Q thread, Q bug, Q worker. So I'm going to just say a little bit of copy and paste action here. We are going to name our main thread. Notice we're in our main function and we're saying the current thread is main thread. Now let's go ahead and do some work here. So we're going to say Q info starting and then our current thread and then let's go ahead and say finished. And then in here somewhere, we're going to say doing stuff seems rather simple at this point, right? It is. Now what we're going to do is we're going to show you how a non-threaded application works and we've done this before. So it's going to look very familiar. I'm just going to call that slot directly. And what does the output look like? Anybody? It's going to say starting, doing stuff. The worker is going to run. So it's going to go in here and do this loop. And then when it's finished, it'll come back here and say finished. This is not threaded. Let's save all and wait for it to build. There we go. So this is boring. This is not what we want at all. This is all running on the main thread. You see working on main thread. So this is important to remember when you get into GUI programming, the main thread is something you never want to lock up because look at what just happened. Our entire application stops and does things one at a time, not fast at all. We don't want that. So let's fix this and turn this into a multi-threaded application. Now, spoiler alert, this will work just fine because there's no parent, but we're going to demonstrate a slight issue here. Let's say we got a pointer. So I'm going to say worker. Let's actually turn this into a pointer. Again, I did say I was a bit rusty because this is a Q object. We could give it a parent. But if we do that, we're going to get an error saying, you know, cannot move object to a thread that has a parent. So it cannot have a parent at all. So bear that in mind. If you tried to move something over there, it's just simply not going to work. Now, we don't want to do this because, well, we want to move that worker to a thread. So first thing we're going to do here is say Q thread. And then let's go ahead and name this. I'm going to say thread and we're going to set the object name to worker thread. It doesn't have to be name worker thread. You can call it anything you want. You can call it fuzzy kitten if you felt like it. But notice we have two very distinctly different objects here. We have a worker and we have a Q thread. And it's already saying value stores is initialized and then potential memory leaks. So now this thing is freaking out. But don't worry, we're not going to have a memory leak. We're going to take this thread and this worker and we're going to smash them together. Or more appropriately, what we're going to do is we're going to say worker dot move to thread. This is the confusing bit because you'd think you'd want like thread move object. But no, we're going to say worker move to thread. And then we define what thread we actually want to move it to. But we're just going to simply move it to that thread. Notice that Clang finally stopped annoying us with all those warnings because now it knows what we're doing. We have two other problems. First, we need to start our worker when the thread starts. Because if we just run this as is, guess what? We've moved the worker, but the worker doesn't know what to do. It doesn't know when to start. And we can't start the worker on the main thread. So we need to tell the worker when the thread starts. This is very, very simple. What we're going to do is we're going to say Q object, we're going to connect. And we're going to connect our thread. I'm going to say Q thread and we want the started. And we're going to connect that to our worker. And we're going to connect that to the run slot. This really is the power of Q right here is you have this ability to connect things and it's just going to automatically know what to do. So when the thread is started, the worker is going to call the run function which is going to kick off. You guessed it. This little loop right here. This is going to be that hopefully light bulb moment. This delete later. Flip back to our main. What have we done? We've created a pointer. This is an unmanaged pointer and we're going to have a bad time. There are multiple ways of doing this. We could use auto pointers, but a very simple way of doing it is just saying you know what? Delete later when we're done with it. So it's just going to get rid of it all together and we don't have to worry about it. Again, there are better ways of doing that and we will cover those in future videos. But right now, if you're super worried about this little example having a memory leak, simply call this delete later and it will schedule this object for deletion inside of Qt. All right. Now the final moment of truth here. What I'm going to do is I'm going to say red start. So we're going to start that thread up, which is going to run our worker. Let's go ahead and run this and see what it looks like. Now it seems a little confusing at first because it says starting, doing, and then finished. Wait a minute. Finished, but our worker is still going and then the worker is finally deconstructed. So let's really illustrate this a little bit better. Notice that we are starting doing stuff on the main thread and now we're working on the worker thread. So we've successfully moved it over to another thread and we've deconstructed that object. I'm going to add in a little bit of code here just to illustrate and you don't really need it. It's just for illustration purposes. All right. So we've got doing stuff and let's get rid of this guy here. And we're simply going to do a loop. It's almost identical code to the worker thread here and we're just going to say working and then whatever number on the current thread and we're going to sleep for 500 milliseconds. So now we have two threads at the same time running and this will be a little more clear just how powerful this is. Run and now you can see we are working on the worker thread, working on the main thread, working on the main worker and it just kind of as the scheduler sees fit it's going to do its thing. This is what I mean by this is how powerful threading is. This simple little example we can now work on multiple threads with ease and we can clean up when we're finished. 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 Voidromes 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.