Zeke
Zeke

Reputation: 121

Using and Implementing a Singleton Correctly

I'm dabbling in writing a multithreaded game structure. What I have below is the basic structure. EventManager, LogicManager, and Renderer are all threads. They read/write from a universal Gamestate class that will handle all shared resources between the threads. From what I understand Gamestate should technically be a Singleton. Is that correct? I would also like to know how to implement it as an "early initialization singleton" as described here: http://www.oodesign.com/singleton-pattern.html#early-singleton, except in C++. I'm afraid I'm not too well versed in C++ statics and as a result I don't know where to put the "private static Singleton instance = new Singleton();" line in C++. I'm aware I could get the same effect with a workaround, however I would like to try it this way.

int main(){
    Gamestate gs;
    EventManager em(&gs);
    LogicManager lm(&gs);
    Renderer renderer(&gs);

    lm.start();
    renderer.start();
    em.eventLoop();

    return 0;
}

Upvotes: 1

Views: 208

Answers (2)

user1773602
user1773602

Reputation:

If you absolutelly need a global game state object, then make it global. Declare it as a global (smart) pointer, initialize it manually in the begining of main and destroy manually at the end. By doing this you

  1. Avoid multithreading problems
  2. Totally control in what order your singletons are initialilzed and destroyed
  3. Make it easy to inject a mock object for unit testing

As other people pointer out, singleton is overrated to the point of being an antipattern. Avoid.

Upvotes: 1

Ran
Ran

Reputation: 6159

As @juanchopanza and @Dietmar commented, there is really no reason why the game state should be a singleton.

Furthermore, I can think of a few reasons why it should not be one:

  1. Unit testing is made very difficult by singletons. It is a lot more difficult to mock a singleton than an interface.

  2. Suppose one day you want to expand you game? For example, what if one day you want to have the game logic run on a server and have your players run clients (think multiplayer)? In such a case you may want to have more than one game state in your process and a singleton limits you needlessly.

  3. If you want to do things with the game state such as to serialize it to send between machines, or maybe save and load it from a file, making the game state a singleton makes it more difficult. It becomes cumbersome to use standard serialization frameworks.

  4. It is difficult to inject dependencies into singletons. What if you need some components or data in order to initialize your game state? In that case you will have some period of time where some thread might access the game state instance even though it is in an inconsistent state.

I could probably think of more reasons. Anyway my advice would be to define interfaces for all the components, and have each component receive the components it depends on as interfaces as constructor parameters.

This makes it easier to write well-decoupled classes, keep classes from bloating, and have good unit tests.

Then you could use any inversion of control framework to auto-magically tie all the components together in your game initialization code.

Upvotes: 1

Related Questions