 Okay, we're going to talk about resource acquisition is initialization. And what does it really mean? And while you can read this whole thing, shorthand what it means is allocation is done during the creation of an object and resource deallocation is done during the object's destruction. So when you create an object, you gather the resources. When you destroy the object, you release the resources. And let's look at a pretty solid example of that. Pretty solid example, no pun intended. Or was there a pun intended? Anyways, so we're going to go to a console app. We're going to say, cute5, sign patterns, and this is 4-5, bang bang, and just going to put some notes in here. And it says it makes it easy and cute follows RAII mostly, not all the time. So we're going to make a simple server. When I say simple, there's actually not a lot simple about this. If you're a beginner, this is going to make your head explode, just fair warning. So we're going to add in networking, and I want to actually put that in my notes. Sometimes people will download this code and they'll not understand why it doesn't work. So we have got our main file, and we're going to actually make a multi-threaded TCP server using a thread pool. Whew, say that after a few cocktails, okay. So because we're going to be working with the thread pool, we need to kind of do things a little bit differently. And we're going to go add new, and I want to add a class, MSA, myConnection. And in our connection, we're not going to make this a queue object. We're just going to have this as a normal C++ class. And now we're going to add a new myServer, and this of course will be a queue object. Now there's a reasoning behind this. It just makes it super simple, and the connection is going to be a queue runnable. And queue runnable is not a queue object. What? Okay, so think of it in terms like this. The connection is the actual connection, the TCP connection. We're making a wrapper around it to handle that thing. So I pasted some includes, queue object, queue runnable, the socket, debug, and thread. So yes, we're going to be working with sockets and threads in this video. And right here, we're going to just say queue runnable. And if you've worked with thread pools before, you know, these things are pretty sweet. We're going to add the runn function. So what happens under the hood is you'll create a runnable, you'll hand it off to the thread pool, and the thread pool will call run in the background here. And when we call run on this, it's going to actually be on a separate thread. So pretty cool how that works. I'm going to get rid of that little guy there. And I'm going to say, why does it say public public? That's annoying. All right. So we're going to say void, handle, or actually let's do set handle, you know, there's probably an easier way of doing this. Sometimes I just like to argue with the editor. I don't know why. So, so we're going to say socket, I'm going to make a pointer called msocket, maybe. There we go. And then we're going to make a queue int ptr called mhandle. And then we're going to create a getter and setter. Now notice this has to be a pointer. Queue object, there's a reason for this. I'm just going to paste my notes right in there rather than try to type all that. Queue objects cannot move threads easily. And what I mean by that is if you create an object and then you try to move it to a different thread, which you've probably done hundreds of times, sometimes that doesn't work too well. So you get what's called a cross thread operation. Queue object cannot create children for a parent, keyword parent, your parent child hierarchy, on a different thread. So if you have threads A and B, and you try to create a thread on B with a parent of A, bad things happen. Seems super confusing because it is super confusing. Let's switch over here and let's actually flesh this out. And we're going to just go right here. I'm going to say queue info, oops, don't know why I even did that, queue thread. We want that current thread. So we want to know what thread we actually did it. Do not create the socket here. We're talking about RAII, but you would think, hey, we're creating this, we should create it here. No, do not do that. Why? Because this will be created on the original thread with the parent and this is going to be shoved into the thread pool as a separate thread. Oh, that gets frustrating. So now, because we're working with RAII, we need a deconstructor as well. Now, somebody out there is probably screaming, well, if you're not doing it here, it's not RAII. The shorthand version of RAII is that you use the resources, or you create the resources when you need them and you get rid of them when you no longer need them. You use the resources through a full object life cycle if you don't need them and we're going to demonstrate that. So I'm going to say, just grab this guy. So we destroy that and I'm going to say, if M socket, so if we have a socket, we're going to say, if M socket is open, we're going to close that and then we're going to get rid of that socket. So super confusing. Is this RAII? Yes. And here's why. This may be the constructor of the class, but this is when the class actually gets run on a thread. So this is where the execution starts, gather the resources here. And we're going to say, execution ends, release the resources. This is why RAII gets a little bit confusing because you're going to be inclined to do it here and you really shouldn't because we're going to have a cross thread operation that will completely break this thing if we try to do it some other way. Hmm. All right. So I want to, I want to add in another little guy called handle connection. And then I'm going to right click and bang. There we go. I'm going to move this right up under here so we can see very easily what's going on. So when run is called, this is what we need to really focus on here is we're going to start running on a different thread. And that's why I've got this current thread because you'll see when we run this, how that thread is going to actually change. Now we need to do our RAII, meaning we need to actually create that socket. Now we've created a pointer. This is kind of the pain part here. Hmm. Because we're working with a pointer, now we have resources we need to track. This gets super frustrating. And we're going to set descriptor, there it is. And we want to get the M handle, which we're going to set when this thing is created. And we are going to wait for disconnect, or actually wait for connected, sorry. Wait for disconnected. We'll be there a while. And then we're just going to handle the actual connection. So when this is run, this is going to be on a separate thread inside the thread pool, and then anything that we call is also on that separate thread in the thread pool. That's kind of why I broke that up. So you could see that, hey, anything you call on the thread stays on the thread, unless you specifically try to move it off, at which point it may explode. All right, now we're going to handle this connection. We're going to say Q byte array, and let's call this data. And I've got some code. I'm just going to the old copy and paste bang. We're going to just say data panhello world, we're going to write it, we're going to wait for those bytes to write, and then we're going to close that socket, at which point the runnable has nothing to do, and the thread pool automatically will delete this because we're going to set this to auto delete, which means it's going to come up here on yet the main parent thread, and it's going to release this bad boy. And that socket is going to have to be deleted. So there's our full object lifecycle for that socket, or RAII. As it starts here in run, and ends in the destructor, again, we didn't do it here because we'll have a cross thread operation, and it's going to get really ugly if we try doing that. Super, super confusing, but that's why I'm doing this example, and not a very basic class, because someone somewhere will try this and then wonder why they have all sorts of issues. So let's go into our server, it's just going to paste in the includes. We have in order qobject, qtcpserver, qthreadpool, qthreadqtabug, and our connection class. All right, so let's go into slots, and I'm going to say void, and I want about to quit. And now we want to actually go in here and say qtcpserver because we are making a tcpserver, and now we need to handle this incoming connection. And again, this is very error prone depending on what version you have. So always trust whatever type it's putting here. If you ever have an incoming connection that never fires off, that would be why is the type is wrong. This used to be like a qint64, an int, or something like that. So as they move from one version to the other, it's gotten a little bit finicky here. I'm missing, are about to quit, and there we are. All right, so our server, super, super simple. We're going to just kind of dumb this down just for the sake of time, or we'll be here all day. We're going to go ahead and close this, not sure if we're going to use that. I just want to add that in in case somebody downloads this and decides they want to use it. So we're going to go ahead and make our runnable my connection, and let's call this client, memory leaks, memory leaks everywhere. So I'm going to actually put in danger, no pointer, or a pointer with no parent. So why are we doing it this way? Because if we try to set the parent, we're going to have some sort of cross-thread operation. Frustrating. So this is how we do memory management for the thread pool. We're going to say client set handle. That way we can get the handle of the incoming socket connection. In case you're really super curious what that is, it's just a number. The OS says, hey, here's a number, and it may be like 16, 55, 255, 6,000, whatever, of whatever socket on the underlying operating systems that's sitting there waiting for the connection to be accepted. But now we want to do our memory management. So we're going to say set auto delete true. And I believe this is true by default, but I simply don't trust it. So I always set auto delete true. Then queue thread pool. And I'm going to say global instance. That's right. Every single app has its own global instance. And I'm going to say client. So we're going to start our runnable. And I'm going to just copy and paste in some notes. So if somebody downloads this, they're not completely clueless what we're doing. So in order, incoming connection fires off from our server. We make a client, but we are in danger because we have a pointer with no parents. So we need to manage that memory. We're doing that here when we're telling the thread pool to take ownership of that and delete it when it's done. And then we're just saying, hey, set that handle. So inside of our actual connection object, when we run, we can actually set the socket descriptor to the handle. So we tell the underlying OS, hey, you gave me a number of 55. I'm going to go ahead and take ownership of that socket. And I'm going to now read and write the data out of that socket. If that seems confusing, it's because it is. Socket programming has always been a pain for just about everybody everywhere. So let's jump back in here. Now let's make this thing actually work. So we're going to say, include Q object and include my server needs some screen real estate here. There we go. And I'm just going to say my server. And let's go ahead and call this server. And now we're going to simply connect the signal and slot up. So I'm going to say Q object connect. And I want to connect to this Q core application. And I'm going to say, I want the Q core application about to quit. You were wondering where that was coming in. OK, so now when the application is about to quit, we're just going to simply shut that server down. So we're going to say server. We want the my server about to quit. So when the app stops, the server stops. Otherwise, this thing may hang in the background indefinitely until we force it to stop. And that gets super frustrating. If not server, and I want to say, listen, and I want Q host address any changes to whatever you want on your operating system, and I'm going to do 3372, again, pick a port that's not in use and isn't going to piss off somebody's virus scanner. And I'm going to say server.airstring. In case you skipped it, I did have a video that I made where I used a port and I had no idea at the time, and the port was known to be a virus port that a common virus used and I didn't even know about it. And so somebody said, hey, man, you infected my system. I typed the code exactly as you typed it, and now I have a virus and I'm just I had to explain to them that's not how this works. All right, so our server and all its glory. Let's give it a good build. Make sure we didn't screw anything up because that was a boatload of typing. And there's a whole lot of scanning and stuff going on. Let's do that again just to make sure. All right. And listening. All right. What port did we do 3372? So I'm going to pull up and tell that and all right. There is our full socket life cycle there. So listening and then it was constructed on this thread and then it was constructed on this thread and there is our actual client right here and then constructed constructed everywhere. Let's redo all of that. I got a feeling I had a little copy and paste friendly. Ah, destroyed. Yes. Not constructed running constructors everywhere. That's embarrassing. Super easy to fix. All right. Let's try that one more time. So it is now listening pop. There we go. Didn't want to work with me there. So we're just going to tell that into that server and that should be a little more easy to understand here. So we have constructed on this thread. We are running on that thread. It is now pulled. We're handling that connection and then we're destroying. So there is our full object life cycle. Now the whole point of this isn't really cross-threaded TCP server operations. The whole point of this is RAII resource acquisition is initialization and what that simply states is create the resources when you need them, destroy the resources when you don't and they take it a little bit kind of a written in stone approach where they say resource allocation is done during the object creation by the constructor while resource de-allocation is done during object deconstruction by the deconstructor but this is an example of when you simply cannot do that. If we were to go into our connection and create the socket here we'll get a cross-thread operation. So we simply can't. So we do it at the earliest possible point which is when the thread starts or the execution starts.