I’m going to first talk about a bit of my motivations and goals, so if you don’t want to hear that you should skip to the next section for the good stuff. Anyways, I’ve been working on a game engine this past week and it’s really opened up my eyes to how little I know about C++. After a few hours of browsing the C++ subreddit, I’ve realized that I can’t even understand at least half of all the posts on there. That is why I spent a couple of hours putting together a list of C++ topics that I want to learn and understand, from things like RAII, SFINAE, to memory alignment and template metaprogramming; I want to learn it all, and I’m starting with this post about RAII.
What is RAII
RAII stands for resource aquisition is initialization, which is essentially the idea that the lifetime of a resource that has to be acquired should be bound to the lifetime of an object. Essentially, upon initialization of an object, we are also aquiring resources which have their lifetimes bound to that of the wrapper object. Some people are pushing to call this scope bound resouce management, since the resource is freed once the object goes out of scope. This fundamental programming technique is used to guarantee exception safety; Consider this example:
The above code locks the mutex on the first line in the try block, and calls unlock later on in the program. However, once the exception is thrown, the rest of the try block doesn’t execute and the program control falls to the catch block. This means that the mutex is never unlocked properly and when the lock function on the mutex is called within the same thread again, the behavior is undefined and will most likely deadlock. Now consider the following class:
With this basic implementation of a lock guard, we have bound the mutex lock cycle to the lifetime of the LockGuard class. Now, when we try the same block of code again, we get our resources properly cleaned up:
With the new implementation, the mutex is unlocked if the try block completes successfully or when an exception is thrown since the unlock is now in the destructor of a stack allocated object, which goes out of scope once program control is passed to the catch block.
The idea of scope bound resource management is not just limited to mutexes, it can be used for things like file handles, sockets, heap allocated memory, basically anything that has a clear initialize/cleanup structure. A lot of times, these things are already in the standard library, like the Lock Guard that we implemented above, or things like smart pointers. Personally, I have used this technique to code certain aspects of my game engine, consider the following texture class(taken from the engine I am currently working on):
With the way I have implemented the Texture class, the SDL_Texture object held within the class will always get freed properly, because I put the DestroyTexture function into the destructor. This way, I don’t have to worry about freeing the texture myself in my main programs, and leads to overall cleaner code.
As I am not by any means an expert in C++, so I’m going to provide some more resources for extra reading. Here is the cppreference page for RAII, and here is a pretty detailed stackoverflow explanation about the concept. If reading isn’t your thing, this video has a decent explanation as well.
As this is my first technical blog post, combined with the fact that I’m not quite fluent in C++, I would greatly appreciate any feedback/criticism. Feel free to leave a comment on this post or send me an email at firstname.lastname@example.org.