views:

117

answers:

4

I have a singleton instance that is referenced throughout the project which works like a charm. It saves me the trouble from having to pass around an instance of the object to every little class in the project. However, now I need to manage multiple instances of the previous setup, which means that the singleton pattern breaks since each instance would need it's own singleton instance.

What options are there to still maintain static access to the singleton? To be more specific, we have our game engine and several components and plugins reference the engine through a static property. Now our server needs to host multiple game instances each having their own engine, which means that on the server side the singleton pattern breaks.

I'm trying to avoid all the classes having the engine in the constructor.

Edit: The engines isn't guaranteed to be running on a unique thread. Each engine has a unique ID that can be used to identify the instance.

+3  A: 

The closest thing you might be able to do is use the ThreadStatic attribute on your singleton instance variable. This will maintain static semantics in terms of access, but each thread will have its own instance.

public class ThreadStaticSingleton
{
    [ThreadStatic]
    private static ThreadStaticSingleton instance;

    public static ThreadStaticSingleTon Instance
    {
        get 
        {
            if(instance == null) instance = new ThreadStaticSingleton();

            return instance;
        }
    }
}

That being said, that could very easily not be what you want. If you need to have either multiple threads access the same instance via the static variable or have one thread access different instances by the same variable, then this won't work.

Put another way, this will work if both of the following are true:

  • Each game engine runs on its own thread
  • Each game engine only runs on one thread

Otherwise, you'll likely have to go the factory pattern route, where each engine passes some sort of identifying information (even if it's just this) to a static function to obtain the instance rather than just using the Instance property.

Adam Robinson
Really cool feature, but not quite fit solution for this problem. Several engines will be running on the same thread. Having a key causes the same problem - all the classes using the engine would need static access to the key, and then we're back to basic.
Qua
@Qua: This is, by definition, no longer a singleton. It sounds like an instance variable of your formerly-singleton type on your game engine is what's called for. I don't think there's going to be a way around this without some refactoring.
Adam Robinson
We changed the structure to having each game instance running on seperate threads. We properly should have from the start anyway. Awesome attribute.
Qua
+2  A: 

You could implement a multi-instance singleton, using a Dictionary of singleton objects. Each of your game instances would then need to use a different key.

There are other ways of doing it not using a Singleton, but something like this might work for you (note: I didn't compile or test this, but it might give you a start).

public class MySingleton
{
    private static Dictionary<string, MySingleton> myInstances = new Dictionary<string, MySingleton>();

    private MySingleton()
    {
        // construct instance
    }

    // note: could also implement using an indexer
    // also note: this is not thread-safe, but you could add a lock around it
    public static MySingleton GetInstance(string key)
    {
        if (!myInstances.ContainsKey(key))
        {
            myInstances.Add(key, new MySingleton());
        }
        return myInstances[key];
    }

    // other methods
}
Andy White
And how would my classes know what key to use? I don't see how this fixes anything at all. Before I needed static access to my singleton - now I need static access to some arbitrary key.
Qua
If each of your game instances needs to access a different instance, you'll have to identity each of your instances somehow. How do you identify each of your unique game instances? Do you have a GameID or a GameName or something?
Andy White
Say I create a game engine instance with the key 'kek'. Now all the instances of the classes referencing this specific game engine would be required to know the key in order to reference the game instance. How would all these instances know the key unless I passed it to them in some manner? Each game / engine has a unique ID.
Qua
If you don't want your other game objects to have to track a key, you might want to start looking at a Dependency Injection framework, to automatically inject instances of things into your classes. See Dan Bryant's answer. Scaling a single-instance design out to multiple-instance support is not trivial, you have to do something to differentiate the unique game instances.
Andy White
A: 
Steven Mackenzie
+4  A: 

This case is where the Singleton pattern breaks down. Having a single place where all of your code could retrieve an instance was convenient, but now you need to keep multiple instances. However, you're right that it's very annoying to pass context instances all the way through the constructor chains of your object tree. One solution to this problem is to use an Inversion of Control framework, like Ninject. It's a bit of a design investment (since it takes some time to get used to using IoC), but it's particularly good at resolving these issues, where you want to use dependency injection (passing your GameEngine to your various classes), but don't want to write a bunch of glue code just to pass the references around.

That said, if you only have a single context like this (i.e. it's only the GameEngine that's your singleton), then it's probably simplest to just add it to all of your constructors.

Dan Bryant