views:

224

answers:

6

I have a requirement to have a only a single instance of a class at any given point of time. Singleton is the obvious candidate. But I have some other conditions that are not typical of a Singleton.

  1. The lifetime of the singleton is not the lifetime of the program. This object has to be created every time I enter a particular state and destroyed when I leave the state. For the entire duration of the state, I cannot create another instance of the class.
  2. Every time, I enter the state and create a new instance, I need to pass a variable to the singleton. Its a number, based on user selection.

So my implementation has the following static functions -

// To be called exactly once, everytime I enter the state
void MySingleton::CreateInstance(size_t count);

// To be called any no. of times during the state
MySingleton * MySingleton::GetInstance();   

// To be called exactly once, when leaving the state.
void MySingleton::DestroyInstance();        

Now this implementation is a major detour from conventional singleton implementation.

Is there any problem with such implementation?

Are there any better alternatives?

+11  A: 

If you create an instance every time you enter a given state and destroy it every time you leave that state, it would make more sense to have the instance be owned by whatever is managing state transitions (or some other entity that is aware of the state transitions).

For example, you could have a smart pointer to an instance as a member variable of the state manager. When you transition into the state you can initialize it to a new instance and when you transition out of the state you can destroy that instance.

In my opinion, this would be cleaner than and preferable to using the singleton design (anti-)pattern.

James McNellis
Would be my solution too. Another possibility is to make that manager a singleton, but only if this solution does not apply. In general, avoid singletons if you can.
Emile
A: 

I think this solution is expensive in performance time. I'd create exactly one instance, and change the creation function to:

void MySingleton::reset(size_t count);
Baltasarq
+4  A: 

Is there any problem with such implementation?

Yep. The problem is that this is not a Singleton, because it is not what the "Singleton" pattern is all about. It's a simple variable, local to that state which you enter and leave.

Actually Singletons are just glorified globals, alive throughout the application's lifetime and should be prevented whenever possible anyway. Your "Singleton" isn't a global, it's a state-local.

sbi
Glorified Global, I agree... But I have absolutely 0 problems using them in place of globals to encapsulate logic that several modules need to use on the same data. I agree though that the pattern does not fit here.
San Jacinto
+1 for reducing the problem to its essence: the variable is local to the state, which might even be a specified scope.
Paul Nathan
@San Jacinto: I will happily agree that a Singleton is often better than explicit global variables. Usually, you shouldn't be using a Singleton or global variables.
David Thornley
@David good enough :)
San Jacinto
+2  A: 

The concept you are describing could be ensured by a class like this:

template<class Guarded>
class single_instance : private boost::noncopyable {
   static bool alive;
public:
   single_instance() {
      if (alive)
         throw std::runtime_error("instance already exists");
      alive = true;
   }
   ~single_instance() {
      alive = false;
   }
};

template<class Guarded>
bool single_instance<Guarded>::alive = false;

If you derive your class from this, it will be ensured that you can always only create one instance at a time:

class myclass : single_instance<myclass> {
public:
   myclass(size_t count);
   ...
};

You can now implement and instantiate myclass like a normal class, without the need for factory functions and getInstance methods. Trying to instantiate a second copy before the first one is destroyed will throw an exception.

sth
Sometimes, Boost is NOT the answer (for instance, we do _not_ have an environment where I work that can compile Boost with the current toolchain, and we aren't going to abandon that toolchain just for kicks). Note that I didn't downvote... just that I would prefer to see an implementation that would work with the current standard.
San Jacinto
@san: noncopyable translates directly into a private, non-defined copy ctor /* not defined */ T /* not defined */` whenever you see `boost::noncopyable`.
Bill
@San: As Bill said, the `boost::noncopyable` is only a convenience here. You can also just manually make sure that the class cannot be copied by making your copy constructor private (and, for completeness, maybe the assignment operator too). The main point of the answer is the rest of that template, not the inheritance from `noncopyable`.
sth
+1  A: 

If it's one-per-state, then make it from within your state object and make the constructor private, friend state.

DeadMG
+1  A: 

I fully agree with "Singleton is just another form of global" and it should be avoided.

If your boss is insisting, you can try something like this:

class MyUtil
{
protceted:
 static MyUtil* m_Singleton = NULL;
public:
 /// Create the singleton if does not exists.
 /// \retun the singleton for this class.
 static GetSingleton()
 {
  if( !m_Singleton  )
   m_Singleton  = mew MyUtil();
  return m_Singleton ;
 }

 /// release singleton instance
 /// Warning: Multi-threading not supported.
 void StateRelease( void )
 {
  m_Singleton  = NULL;
  deleet this;
 }

};