Skip to main content

History: -Singleton

Source of version: 5

Copy to clipboard
            {INCLUDE(page="ogrelex ext tpl")/}
---
__Singleton__ - A class of which only one instance can exist at a given time. This instance can be accessed from anywhere in the program without passing a reference to it around. A useful design pattern, but apply with care.

{maketoc}

!!A general approach
!!!Forum Answer
Taken from here [http://www.ogre3d.org/phpBB2/viewtopic.php?t=7320|here]:

__Mdobele:__Singleton Classes rock. Simply think of it as a way of ensuring that the class you are calling is created only once. That means it can be called from anywhere ( by including header of course ) and you know that your calling the 1 static instance and not creating another instance.

I use them mostly for my main application and then for every single "manager" class that I use.

Here is an example of a Menu manager
{CODE(wrap="1", colors="c++")}// Class Declaration
class MenuManager
{
public :
   
   // Constructor
   MenuManager();

   // Destructor
   ~MenuManager();

   // SingleTon Instance
   // Singleton Instance of our Menu manager
   static MenuManager &Instance();

   // Create Main Menu
   void CreateMainMenu();

private:
   InheritedBase *m_BaseMenu;
   MainMenu * m_MainMenu;
};{CODE}And the .cpp 
{CODE(wrap="1", colors="c++")}//SingleTon Instance
MenuManager &MenuManager::Instance()
{
   static MenuManager instance;
   return instance;
}

// Create MainMenu
void MenuManager::CreateMainMenu()
{
   m_MainMenu = new MainMenu();
   m_MainMenu->CreateMainMenu();
}{CODE}
So in any other file i simply include 
{CODE(wrap="1", colors="c++")}#include MenuManager.h{CODE}
and I gain acess to it Knowing that its the one and only and not another instance. 
{CODE(wrap="1", colors="c++")}MenuManager::Instance().CreateMainMenu();{CODE}
Hope that clears it up a bit.


__bal__:
''IIRC, singletons are a design pattern (a way of creating classes that fits in most projects). There are a lot of different implementations but the point is always the same: having ONLY ONE instance of a class. ''

!!Ogre's approach
!!!Description
Ogre's implementation differs in a couple of points from the approach described above.
* Ogre::Singleton is a template, meaning you must instantiate it with the type, that you want to have as a Singleton. This allows us to handle all Singletons with the same code, which makes the code a bit more maintainable.
* Ogre::Singleton must be constructed explicitly. You must call the constructor of your Singleton class, before you can obtain a reference to the instance. The implementation described above creates the singleton on the fly when the instance is obtained for the first time. The advantage of Ogre's implementation is that you can instantiate it with arbitrary parameters.

The Source can be found [http://ogre.svn.sourceforge.net/viewvc/ogre/branches/v1-6/OgreMain/include/OgreSingleton.h?view=markup|here].

!!!How to use it
!!!!Making a class a singleton
Pretend we want to convert the class MyManager to a Singleton.
{CODE(wrap="1", colors="c++")}class MyManager
{
public:
    MyManager();
    void doSomething();
};{CODE}
So we need to extend and instantiate the Ogre::Singleton template and override the singleton access methods. Our header file will look like this:
{CODE(wrap="1", colors="c++")}#include <OgreSingleton.h>
class MyManager : public Ogre::Singleton<MyManager>
{
public:
    MyManager();
    void doSomething();
    static MyManager& getSingleton(void);
    static MyManager* getSingletonPtr(void);
};{CODE}
You don't have to override -+getSingleton()+- and -+getSingletonPtr()+- if your Singleton is not used outside of your EXE/DLL, but else you have to.
The source file would now look like this:
{CODE(wrap="1", colors="c++")}#include "MyManager.h"

template<> MyManager* Ogre::Singleton<MyManager>::ms_Singleton = 0;
MyManager* MyManager::getSingletonPtr(void)
{
    return ms_Singleton;
}
MyManager& MyManager::getSingleton(void)
{  
    assert( ms_Singleton );  return ( *ms_Singleton );  
}

// The rest of your implementation is following.
...{CODE}

!!!!Making a class (in another namespace) a singleton
If you want to make a class from a specific namespace a singleton, you cannot use the previous method.
Due to C++ specification (C++ Standard 14.7.3/2) you cannot specialize a template (like Ogre::Singleton<T>) in other namespace than its declaration's one.
Here is a complement to the previous technique.

There is two case where you need another namespace :
# Your class is a part of an application directly using Ogre3D
# Your class is a part of a library (DLL) directly using Ogre3D but, like all DLLs, attends to be used by another program.

The two cases are pretty close.
The fellowing code is needed only for the case 2. A good practice when developping a DLL is to define a macro for export/import depending on the building situation (building the lib itself => export ;  build an app with the lib => import).
{CODE(wrap="1", colors="c++")}
// File MyLibPrereq.h
#	if defined(MYLIB_NONCLIENT_BUILD)
// Export definition
#		define _MYLIBExport __declspec( dllexport )
#	else
// Import definition
#		define _MYLIBExport __declspec( dllimport )
#	endif
{CODE}

The header file for MyManager in case 1 :
{CODE(wrap="1", colors="c++")}
#include "MyLibPrereq.h"
#include <OgreSingleton.h>
namespace MyLib { class MyManager; }

template class _OgreExport Ogre::Singleton<MyLib::MyManager>; // export of explicit instantiation

namespace MyLib
{
class MyManager : public Ogre::Singleton<MyManager>
{
public:
    MyManager();
    void doSomething();
    static MyManager& getSingleton(void);
    static MyManager* getSingletonPtr(void);
};
}{CODE}

Now the header for MyManager in case 2. The difference reside in the export directive, here we use our own directive :
{CODE(wrap="1", colors="c++")}
#include "MyLibPrereq.h"
#include <OgreSingleton.h>
namespace MyLib { class MyManager; }

template class _MYLIBExport Ogre::Singleton<MyLib::MyManager>; // export of explicit instantiation

namespace MyLib
{
class MyManager : public Ogre::Singleton<MyManager>
{
public:
    MyManager();
    void doSomething();
    static MyManager& getSingleton(void);
    static MyManager* getSingletonPtr(void);
};
}{CODE}

Then the source for __case 2__:
{CODE(wrap="1", colors="c++")}#include "MyManager.h"

// Template specialization
template<> _MYLIBExport MyLib::MyManager* Ogre::Singleton<MyLib::MyManager>::ms_Singleton = 0;

namespace MyLib
{
MyManager* MyManager::getSingletonPtr(void)
{
    return ms_Singleton;
}
MyManager& MyManager::getSingleton(void)
{  
    assert( ms_Singleton );  return ( *ms_Singleton );  
}

// The rest of your implementation is following.
...
}
{CODE}

For __case 1__ just remove -+_MYLIBExport+- in the template specialization.

!!!!Using a singleton
{CODE(wrap="1", colors="c++")}// Creating the manager. This may only be called once!
new MyManager();

// Obtaining a reference to the manager instance
MyManager& mgr = MyManager::getSingleton();

// Obtaining a pointer to the manager instance
MyManager* pMgr = MyManager::getSingletonPtr();{CODE}
__Note:__ You may call the Singleton constructor only once. Calling it more often will result in a runtime exception.
There is another semantical difference between -+getSingleton()+- and -+getSingletonPtr()+-: If the constructor is not called beforehand -+getSingletonPtr()+- will return a NULL-Pointer and -+getSingleton()+- will throw a runtime exception. So it is probably better to use -+getSingleton()+- most of the time, even though it is slightly slower. But you get a clearer response when you set something up wrongly.

!!Some Links:
[http://www.drizzle.com/~scottb/publish/gpgems1_singleton.htm|Ogre's Singleton Method from 'Game Programming Gems' by Scott Bilas]

[http://home.earthlink.net/~huston2/dp/singleton.html|Huston Design Patterns]

[http://www.gamedev.net/reference/articles/article1825.asp|Gamedev.net]

[http://www.codeproject.com/gen/design/singleton.asp|CodeProject.com]

---
{INCLUDE(page="ogrelex ext tpl")/}
---

        

History

Information Version
Thu 20 of Feb, 2014 15:40 GMT-0000 scrawl 1.7 is pretty old now, so assume 1.8+ is used. 9
Mon 23 of Jan, 2012 11:01 GMT-0000 Beauty added alias page name (because of a link from an old forum topic) 8
Mon 28 of Nov, 2011 16:19 GMT-0000 scrawl Added a note that ms_Singleton was renamed in ogre 1.8 7
Mon 28 of Nov, 2011 16:17 GMT-0000 scrawl 6
Fri 04 of Mar, 2011 10:47 GMT-0000 Nems 5
Fri 08 of Jan, 2010 00:37 GMT-0000 jacmoe 4
Tue 29 of Dec, 2009 09:54 GMT-0000 jacmoe 3
Fri 25 of Dec, 2009 22:21 GMT-0000 jacmoe 2
Fri 09 of Oct, 2009 15:34 GMT-0000 OgreWikiBot Robot: Cosmetic changes 1