Archived

This topic is now archived and is closed to further replies.

Can Singleton be abstracted?

This topic is 5140 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So that if I have a class that I want as Singleton, all I have to do is cMyClass:cSingleton? Not sure if this will work because cMyClass will inherit the static singleton pointer from cSingleton so that if I also do cMyOtherClass:cSingleton then they will actually have instances to the same pointer. I was aiming at an abstract derivable cSingleton class but now I think that I''ll have to settle for simply repeating the singleton specific code in all of my classes that have to be singleton. Unless there is another way. Thanks for any input, Webby

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Havnt check this by compilation, but id guess something like this


template<typename T>
class singleton_base
{
public:
singleton_base(){}
singleton_base& operator =( const singleton_base&){}
singleton_base(const singleton_base&){}
~singleton_base(){}

static T& instance()
{
static T theinstance;
return theinstance;
}
};

//note singleton_base isnt a singleton

class the_singleton : public singleton_base<the_singleton>
{
public:
...
private:
the_singleton (){}
the_singleton& operator =( const the_singleton &){}
the_singleton (const the_singleton &){}
~the_singleton (){}
};
//the_singleton is the singleton, so it need private constructors


you then access the instance by calling the_singleton::instance();

Share this post


Link to post
Share on other sites
Rethinking this design ATM. My goal of singletons was so that I could create a cGraphics object that would control all initialization of DirectGraphics including things like screen resolution, color depth, etc and would provide the interface for minimizing and maximizing the screen etc. I was thinking singleton would be the way to go since other objects might need to create an instance of this class since objects like cObjectManager will be using cGraphics to obtain necessary pointers to the single d3d, etc pointers in the game.

Now I am thinking that it may be cleaner and easier if I just encapsulate these objects into a main cApplication class as static members. This way, there would still be only one copy of each at a time, I think.

Would this work?


class cApplication
{
public:
bool Init();
void Run();
etc...
private:
static cGraphics myGraphics;
static cInput myInput;
static cInterface myInterface;
static cSceneManager mySceneManager;
etc...
};

I have issues understanding this. Say that mySceneManager contains the functionality to have each object in the game Render() itself. Or provides some way to batch render multiple objects at a time. This class would require pointers to the d3d device, etc so how do I cleanly give it a pointer to myGraphics so that it can access these devices?

I don''t want to store a copy of cGraphics inside of the cSceneManager because this would eat up more memory and a lot of code space. The cGraphics would have a method something like
LPD3DDEVICE GetDevicePointer() that should be called to retrieve a pointer to the device. I definitely don''t want to declare myGraphics as a gobal object. I''d like a way for mySceneManager to access this function as necessary and still have only one main copy of the cGraphics object. I thought Singleton would do this but I am reading that it could be more headache than it''s worth. Hope I''m being clear enough to understand here.

Thanks for any help,
Webby

Share this post


Link to post
Share on other sites
Your Singleton "class" would actually be a meta-class, i.e. the class of a class. Its objects would be Singleton classes.
C++ doesn''t directly support user-written metaclasses (Python does ), its metaclasses are hard-coded into the compiler : basic type, array, class types (struct, union, class).

Thus singleton type creation cannot directly be automated (AFAIK).
You can however, use templates to create classes that will contain a single instance of another class (a SingletonHolder).


[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]

Share this post


Link to post
Share on other sites
i believe there is an article in the "articles and resources" section about making a singleton template, which sounds like what you are looking for. sorry, but i don''t have a link.

Share this post


Link to post
Share on other sites
Thanks krez. I did some searching and found this article.
http://www.gamedev.net/reference/articles/article1826.asp

It''s good for templated managers but not for templated singleton. I can see how the templated singleton would work though. I''m going the way of the static members as this IMO is cleaner and easier to comprehend when looking at it. I''ll definitely be putting Manager to use in my code but so far it seems as though I can do without an actual Singleton design just fine.

Thanks again,
Webby

Share this post


Link to post
Share on other sites
Check out Richard Fine's Enginuity series here on GameDev-- specifically part II, page 5. He shows how a templated singleton can be implented like an abstracted base class (with source).

Kudos to Richard because it's a great series. I can't wait to see more.

bpopp (bpopp.net)

[edited by - bpopp on November 13, 2003 3:46:09 PM]

Share this post


Link to post
Share on other sites
Theres this one:


#ifndef __SINGLETON_H__
#define __SINGLETON_H__
{
static T* m_Singleton;

public:
CSingleton()
{
assert( !m_Singleton );
int offset = (int)(T*)1 - (int)( CSingleton <T>* )(T*)1;
m_Singleton = (T*)( (int)this + offset );
}
~CSingleton()
{
assert( m_Singleton );
m_Singleton = NULL;
}

static T& GetSingleton()
{
assert( m_Singleton );
return ( *m_Singleton );
}

static T* GetSingletonPtr()
{
return m_Singleton;
}
};

template <typename T> T* CSingleton <T>::m_Singleton = 0;

#endif


Then when you want to make a class a singleton, just do

class Foo : public CSingleton<Foo>
{
}

#define FooSingleton Foo::GetSingletonPtr()

Now when you want to access Foo, just do

FooSingleton->MemberFunstionName();




Works like a charm


[edited by - Mulligan on November 13, 2003 4:57:23 PM]

[edited by - Mulligan on November 13, 2003 4:57:58 PM]

Share this post


Link to post
Share on other sites
Or, you could use the pluggable factory pattern to write a base class that handles the creation of it''s subclasses (the singletons) although I think the templated method is a bit cleaner/more direct for what you''re trying to do.

peace and (trance) out

Mage

Share this post


Link to post
Share on other sites
The book "Modern C++" describes a template-policy based singleton holder. The source code for the library can be found on sourceforge under the name Loki.

I help maintain it, but I have never used the singleton holder. (I tend to write heavily threaded code, so global variables are a serious pain).

Share this post


Link to post
Share on other sites
quote:
Original post by Magmai Kai Holmlor
The book "Modern C++" describes a template-policy based singleton holder. The source code for the library can be found on sourceforge under the name Loki.

I help maintain it, but I have never used the singleton holder. (I tend to write heavily threaded code, so global variables are a serious pain).


I think thats "Modern C++ Design" Magmai

Loki::SingletonHolder does provide a semi-thread safe policy, though it does have defects.

Share this post


Link to post
Share on other sites
There are two ways that I can think of implementing what you want with a standard Singleton:

1) Pass GetInstance the device reference as part of the call. Clearly, this is not going to work for what you want because you would have to now the device in order to get the device. That said, it works great for a camera; assuming you always know the D3D Device.



class CCamera
{

public:
// Return a Pointer to the Camera using a Singleton.
static CCamera* GetInstance(LPDIRECT3DDEVICE8 pD3DDevice);

// Camera Destructor.
virtual ~CCamera();

// Point the Camera using the provided "view" Matrix,
void Point(D3DXMATRIX matMatrix);

// Point the Camera using the provided vector.
void Point(D3DXVECTOR3 vecXYZ, D3DXVECTOR3 vecTargetPosition);

protected:
// Camera Constructor.
CCamera(LPDIRECT3DDEVICE8 pD3DDevice);

private:
// Static Pointer to the Camera Singleton.
static CCamera *s_CCamera;

// Pointer to the Direct3D Device.
LPDIRECT3DDEVICE8 m_pD3DDevice;
};



2) In this implementation you can call GetInstance to create the Singleton, but you have to call SetDevice when the device changes. It would basically create a global container for you. Notice that the constructor is protected; this will force you to create the singleton using get instance. You can also use friend to restrict access to the SetDevice function, but this would create a coupling that you may not want.



class CCamera
{

public:
// Return a Pointer to the Camera using a Singleton.
static CCamera* GetInstance();

// Camera Destructor.
virtual ~CCamera();

// Set the devive after you call get instance.
void SetDevice(LPDIRECT3DDEVICE8 pD3DDevice);

// Return the D3D Device.
LPDIRECT3DDEVICE8 GetDevice();

// Point the Camera using the provided "view" Matrix,
void Point(D3DXMATRIX matMatrix);

// Point the Camera using the provided vector.
void Point(D3DXVECTOR3 vecXYZ, D3DXVECTOR3 vecTargetPosition);

protected:
// Camera Constructor.
CCamera(LPDIRECT3DDEVICE8 pD3DDevice);

private:
// Static Pointer to the Camera Singleton.
static CCamera *s_CCamera;

// Pointer to the Direct3D Device.
LPDIRECT3DDEVICE8 m_pD3DDevice;
};




_______________________________________
Understanding is a three edged sword...

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You need to make a private copy constructor too Sean, otherwise the compiler will generate a public one for you, allowing your singleton to be copied, in which case it wouldnt be a singleton

Share this post


Link to post
Share on other sites
The basic C solution to implement singleton objects is using static variable...a solution to make a class singleton without statics is to use templates...



template<class T>
class singleton
{
public:

static T& instance(){
static T theinstance;
return theinstance;
}
};


Then you can make every class singleton simply by specify it



typedef singleton<myclass> singleton_myclass;



And use it in your code



void foo1(void)
{
singleton_myclass().instance().method1();
}
//
//
void foo2(void)
{
singleton_myclass smc;

smc.instance().method2();
smc.instance().method3();
}



Of course this is only a trick to hide the ''static nature'' of a singleton object...

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by Magmai Kai Holmlor

quote:

Loki::SingletonHolder does provide a semi-thread safe policy, though it does have defects.


How so?




Its explained in the book, chapter six. The problems come from certain symmetric multiprocessor environments.



Share this post


Link to post
Share on other sites
quote:
Original post by Magmai Kai Holmlor
quote:
Original post by msn12b
Singleton is a hack. It causes the exact same problem it tries to solve.



The implementation is particularily problematic in C++. In other environments, it''s not so hairy.

Not like Java, eh....

Share this post


Link to post
Share on other sites