Phil Hassey - game dev blog
Phil Hassey as Snidely Whiplash
"You can't buy awesomeness.
You're born that way."

Is this a safe pattern for auto-registration?

Hey,

I’m trying to have various components in my game pre-register themselves upon startup of the game. I’m using this pattern:

Here’s my registration code that is in one .cpp file. The register_init() function is available from anywhere:

std::vector &get_init() {
    static std::vector goods;
    return goods;
}
bool register_init(Init *v) {
    get_init().push_back(v);
    return true;
}

Here’s how I auto-register some init code from some other file by calling register init to initialize a variable:

int _is_levedit_init = register_init(new LeveditInit());

Is there some case where this would NOT work or is somehow a really bad idea? Or is there some pattern that is better to use?

-Phil

6 Responses to “Is this a safe pattern for auto-registration?”

  1. Mykhailo Says:

    I think it should work just fine. As another approach for auto registration I saw, it was usage of intrusive list and adding current object to the list in constructor.

  2. philhassey Says:

    After a bit of thought, this all seems like a misguided idea.

    This seems much safer and more predictable. It’s not “automagic” but it requires less keystrokes to attain the same effect. So that’s more of a win in my book.

    #define DOINIT(v) void v##_init(Game &g);v##_init(g);

    void game_init(Game &g) {
    DOINIT(levplay);
    DOINIT(levedit);
    }

  3. dukope Says:

    That would be my suggestion as well. Way easier to manage an explicit list of system inits in one place. Both for dependencies and code clarity, I think your second solution is much better.

  4. dukope Says:

    Actually, one change I’d suggest is this:

    #define DOINIT(v) void v(Game &g);v(g);

    void game_init(Game &g) {
    DOINIT(levplay_init);
    DOINIT(levedit_init);
    }

    … So when you search the code for levplay_init, it has two hits: the function itself and the call from game_init. Otherwise at some point in the future (speaking from experience here), you’ll spend a few moments confused about why your levedit_init function isn’t referenced from anywhere and it’ll take a callstack to figure it out.

  5. Danyal Says:

    Don’t the two approaches do the same thing? I don’t see what was automatic about the first approach. But then, I am a bit slow.

  6. philhassey Says:

    @dukope good call. Explicit is always better than implicit.

    @Danyal the first approach actually added stuff to a vector prior to main() being called by using static / global variables.