jeremyong / SDLpp

Lightweight C++11 bindings to SDL2
zlib License
36 stars 5 forks source link

Why not use RAII for SDL init and quit? #2

Open soryy708 opened 10 years ago

soryy708 commented 10 years ago

The way it is at the moment, you have to do an sdl::Init(); in the beginning of your program. atexit(Quit) makes it so that you don't have to quit when the program terminates.

However,

  1. If you call Init more than once, you initialize everything more than once. Could do trouble.
  2. If you call Quit even once, it will be called again when you exit. Doesn't seem to do much trouble, but still sucks.
  3. You can either initialize SDL any time you want, or mess with init & deinit if you're a perfectionist. Messing with init and deinit to get exactly what you want is just too C-ish and beats the purpose.

Consider making a handle class to init and deinit using RAII.

class Handle
{
private:
    static unsigned int instance_count;

public:
    Handle()
    {
        if(instance_count == 0)
        {
            // Initialize sdl
            if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
                throw 0;
            }

            // Initialize sdl_ttf
            if (TTF_Init() == -1) {
                throw 1;
            }

            // Initialize sdl_image
            const int image_flags = IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF;
            const int initialized_flags = IMG_Init(image_flags);
            if ((initialized_flags & image_flags) != image_flags) {
                throw 2;
            }
        }
        ++instance_count;
    }
    ~Handle()
    {
        --instance_count;
        if(instance_count == 0)
        {
            IMG_Quit();
            TTF_Quit();
            SDL_Quit();
        }
    }
};

So if for some reason SDL's lifetime is bound to some class in someone's game, they can do that elegantly.

jeremyong commented 10 years ago

Looks good. Call it sdl context or something and make a PR

jeremyong commented 10 years ago

Although, no need to use instance counts. prefer a shared_ptr or something for thread safety and such.

soryy708 commented 10 years ago
  1. But I'm not sharing any pointers here.
  2. shared_ptr is slow.
  3. How can you apply a shared_ptr to this?

I'll make a PR once I'm able to compile. atm I'm kinda blocked by Issue 1.

jeremyong commented 10 years ago

Actually, on second thought, I'm not convinced that any change is necessary. It's very C-ish yes, but subsystem it represents is still a C subsystem at the end of the day. Semantically, I don't know what it should mean to init SDL multiple times or what the object holding a count to the handler would represent.

Can you give me a use case for why you'd want anything other than a very simple init at the beginning and quit at the end?

soryy708 commented 10 years ago

Consider putting an sdl::Handle in a class that uses something that requires SDL to be initialized. Well, in the C way, you'd have to SDL_Init beforehand. However, with sdl::Handle you can just put that in the class and be done with it, not worrying about whether stuff is already initialized or not yet. This would make things easier in big projects, projects with multiple contributors, and bad programmers. Overall, would make your API a lot more powerful without any cost. Why not?