Singleton Implementation

Started by
6 comments, last by EbonySeraph 21 years, 4 months ago
So I got me awesome Game Progamming Gems Vol 1 book and bam, there is a technique very relevant to what I need in my current project - singletons. I guess I could do the simple way of implementing them and rewrite the code for every class. But I know that was is crap. So I wanna use the template method. Only I don''t really understand what the code int the book means exactly... The biggest part I dont get is the constructor definition:
  
template <typename T> class Singleton
{
  static T* ms_Singleton;

  public:
    Singleton(void)     //This is the part I really don''t get

    {
      assert(!ms_Singleton);
      int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1;
      ms_Singleton = (T*)((int)this + offset);
    }
};

template <typename T> T* Singleton<T>::ms_Singleton = 0;
  
Also I don''t really understand the last line. I think it''s just initializing the singleton pointer to null, but the syntax need to sink in. "Ogun''s Laughter Is No Joke!!!" - Ogun Kills On The Right, A Nigerian Poem.
"Ogun's Laughter Is No Joke!!!" - Ogun Kills On The Right, A Nigerian Poem.
Advertisement
I hope this post isn''t being ignore because I "should" be able to find an answer somehwere else through searching.

The search function is down, and scanning 7 pages back I couldn''t find it(my board settins wont show more than 7 pages back).

Anyone have an explanation?

"Ogun''s Laughter Is No Joke!!!" - Ogun Kills On The Right, A Nigerian Poem.
"Ogun's Laughter Is No Joke!!!" - Ogun Kills On The Right, A Nigerian Poem.
That implementation is highly suspect. There''s reinterpret casts galore (which means it''s not guaranteed to be portable), and there''s never anything allocated for ms_Singleton. Unless you''ve missed some crucial details, my recommendations are to steer well clear of that Singleton.
I''m not sure of the exact details, but its something to allow you to have a singleton of a derived class with virtual functions (someone help me out here...). You don''t want to take the address of the class, but the address of the base class.

I dunno, its something like that. Help me!

Member of the Unban Mindwipe Society (UMWS)
quote:Original post by Evil Bill
I dunno, its something like that. Help me!

You need to see the intended usage. If you inherit the Singleton by doing:
class C : public Singleton<C>  

Then the constructor of Singleton calculates the offset of the C part of the class from the start of the class and sets ms_Singleton to point at the C part. The asserts will kick-in if you've already done that. The problem is that the offset calculation is platform dependent, and therefore not portable. I suspect there's likely to be problems if used with Multiple Inheritance too. It can be fixed by using the result of casting "this" to T*, which makes the compiler compute the address offset for you without assuming anything about the relative sizes of pointers and ints.

[edited by - SabreMan on December 5, 2002 11:27:40 AM]
quote:Original post by SabreMan
That implementation is highly suspect. There''s reinterpret casts galore (which means it''s not guaranteed to be portable), and there''s never anything allocated for ms_Singleton. Unless you''ve missed some crucial details, my recommendations are to steer well clear of that Singleton.


I''ve actually used this exact implementation in the last 3 games I''ve programmed. I''ve never had a problem with it, though all my games are windows only*

just my 2c,
ratman

*yes becase some people like to be overally anal - this does not garuntee there are no mistakes or problems with this implementation or that it is portable. However in my experience, it works fine.
Okay...so lets assume that the template implementation is crappy. What the hell else do I do? Rewrite all the singleton code for every class I want to be singleton?

Or let supposed I still want to use it....here is a log class that I''m trying to make singleton. It comes up with several unresolved externals when I try to build under VC++ 6.0


  typedef class CLog : public Singleton <CLog>{	public:		CLog();		~CLog();		//Same as open log		CLog(const char * filename);		//Opens log for writing		bool OpenLog(const char * filename);        //Checks to see if log is open for writing        inline bool isOpen() { return m_isOpen; }		//Closes log		void CloseLog();		//Writes text to log		void Write(const char * text);		//Writes number to log		void Write(int num);		//Writes a line of text in log		void WriteLine(const char * text);		//Writes the current date and time to the file to keep records		void WriteDateTime();	private:		//File stream to read/write to		fstream			m_File;		//Is a file open for writing		bool m_isOpen;} LOG, *P_CLog;  


Now, ignoring the fact that a log class shouldn''t/doesn''t have to be singleton, and any other things I may have done horribly wrong. Why do I get unresolved externals using the class, with the singleton definition I wrote earlier.

"Ogun''s Laughter Is No Joke!!!" - Ogun Kills On The Right, A Nigerian Poem.
"Ogun's Laughter Is No Joke!!!" - Ogun Kills On The Right, A Nigerian Poem.
quote:Original post by Ratman
*yes becase some people like to be overally anal

If you stop being so defensive, you might find yourself able to have a sensible discussion.
quote:
this does not garuntee there are no mistakes or problems with this implementation or that it is portable.

Which is pretty much what I''ve said.

quote:EbonySeraph
Okay...so lets assume that the template implementation is crappy. What the hell else do I do?

I told you what to do. Change the constructor to this:


  Singleton(){	assert(!ms_Singleton);	ms_Singleton = static_cast<T*>(this);}  


That should solve the problems.

This topic is closed to new replies.

Advertisement