Archived

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

singletons

This topic is 5498 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

Is there anything wrong with something like this:
        
template <class T>
class singleton {
private:
    singleton();
    ~singleton();

    static T &get_instance( void );
};

T &singleton< T >::get_instance( void )
{
    static T instance;
    return instance;
}
        
I mean, it seems to work, but I didn't know if i violated some rule I can't think of, and will bite me in the ass later. I also remember alot of good discussion on singletons here a while back that i can't seem to dig up, so comments are welcome.
[My site|SGI STL|Bjarne FAQ|C++ FAQ Lite|MSDN|Jargon]
Ripped off from various people [edited by - wild_pointer on November 21, 2002 5:30:18 PM] [edited by - wild_pointer on November 21, 2002 6:01:48 PM]

Share this post


Link to post
Share on other sites
Singleton's get_instance probably should be public, eh?-)

typedef singleton<Foo> FooSingleton;

There are things to consider:
-Foo is the class where you must make constructors private so that outsiders can't create more instances of it
-still, singleton must be able to access Foo's constructor, so you must make it a friend class
-be warned that the instance is created when first invoked, and destructed in reverse order.. So, during program shutdown, some destructors might be calling a singleton that has already been destroyed

[edited by - civguy on November 21, 2002 6:15:39 PM]

Share this post


Link to post
Share on other sites
Actually, I'm pretty sure that isn't truly considered a singleton, though I could just be talking about a particular type of singleton, I'm not sure of the actual "definition" of a singleton, or if there actually is one.

Usually what you'd do is not have a static instance of the object but instead, you have a static pointer to an object that is actually used for dynamic allocation and de-allocation. The programmer explicitly calls a function to construct and one to destruct the object and the class keeps track of whether or not the class is currently initialized.

The reason for that is order of construction. Say you have two objects where one objects construction relies on the initialized version of the other. If the two objects were in separate files, etc. it would be hard to be sure of the order of their construction and destruction. Just making a static instance as you did in your example without isn't really solving that problem.

Once again, what I may be talking about could be a specific type of Singleton, I'm not sure, though this is the only type that I use. I believe that there is a name for what you are doing and I think it's a "monotype," which is not the same thing as a singleton, but I could be mistaken. I'm sure someone can give you a flat out definition if there is one.

[edited by - Matt Calabrese on November 21, 2002 10:57:47 PM]

Share this post


Link to post
Share on other sites
OK, every post here is focusing on some aspect of a singleton (not counting the wrong posts), but none are explaining ...

singleton is a design pattern, with multiple rules, each for various reasons ... there are various partial singleton ideas that have valid uses as well ...

a singleton is a class that A) can only have one instance, period - and B) the instance is globally accesable.

those are the only rules, and anything which follows those rules is a singleton ... now in the real world there are extra issues(such as initialization and shutdown order) to be dealt with.

I have similar templates to yours, but find that there is not any one singleton implementation which works for all singletons, and here are some reasons why (aka issues and tradeoffs)

1. Sometimes you want a singleton to be self managing (ie not need explicit construction / descruction) hence you do what you did with the static member function memeber - which create the item automatically at first call, and destroys it upon program shutdown.

2. Almost always you want a singleton to have private constructors and descrutors, so that it, not the caller, can control it''s lifetime ...

3. Often a singleton will need information at construction time, or need to destroyed in a specific order, so liftimes must be managed somehow.

In your example, you offer extra feature #1, but not #3 (the 2 are pretty much mutually excusive) ... and #2 is really a rule of singletons, that there CAN ONLY BE ONE instance ever, and you do not satisfy that rule for type T ...

There are multiple ways to implement singletons -

1 - (like yours), you make a template which will be the singleton class, which accepts type T which must be a special class which meets the needs of the template (private construtor / destructor, friends of template, etc). This system is not theortically correct, because you can make singleton of int and it would obviously not be enforcing the singleton rule, but compile just fine.

So you see, the problem with your singleton is just that it ensure IT is only instantiated once, but not the type T.

This is not a singleton then, it''s an improved global variable (a singleton without the rules is a global variable) - the reason this is improved, is because access is through a function, and therefore can be changed latter without requiring changes to your clients ...

I use the same thing for my logging classes, where i have logging classes (like DualFileLogManager, and NetworkLogManager), and I have a singleton class called SystemLog which provides the central static access function to a log manager, AND wraps it in semaphore so it''s thread safe ... all preventing the underlying manager classes from being instantiates seperately ... this way there is ALWAYS a system log, just like a singleton, and it''s thread safe ... but you can make other special purpose logs anytime you want, and the thread safety for them is up to you ...

Share this post


Link to post
Share on other sites
quote:
Original post by wild_pointer
What are the drawbacks and what do you recommend instead?
Well, since singletons are accessible anywhere, they complicate your design. If you make a class singleton, then that classes' management isn't necessarily centered in one logical part of your program, but scattered throughout the whole program. You can always pass objects around as parameters, so singleton is usually nothing but a convenient way to get rid of that workload. (it also enforces one instance, which may be needed at times)

This convenience isn't always a bad thing though - we're humans after all. I'd use singleton for object factories, for example. Just don't go using that pattern too merrily or it does bite you in the ass eventually, no matter how well implemented.

[edited by - civguy on November 22, 2002 3:31:52 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by wild_pointer
What are the drawbacks...

It''s basically a global object, and includes most of the drawbacks of such. Many programmers think they are creating a good design if they use a Singleton, on the basis that Singleton is a "Design Pattern", which is strange as all the good designers I know try to avoid global objects.
quote:

...and what do you recommend instead?

Rethinking your design so that it doesn''t necessitate a Singleton - this might require you to flex the design in a different direction. A Singleton should only be used when you want to enforce that a system *must* only have one of something, but it gets abused so that people use it when they only *desire* one of something.

Share this post


Link to post
Share on other sites
quote:
Original post by civguy
I''d use singleton for object factories, for example.

I wouldn''t. It sounds like an artificial limitation - as in what problems does it cause if you have more than one object factory? If you want various parts of your application to use the same object factory, then you organise your design around that. You shouldn''t use various mechanisms and design patterns to allow you to organise your design around an arbitrary rule taken from the solution domain.

Singletons Are Evil.

Share this post


Link to post
Share on other sites
quote:
Original post by SabreMan
Original post by civguy
I''d use singleton for object factories, for example.
===end quote===
I wouldn''t. It sounds like an artificial limitation - as in what problems does it cause if you have more than one object factory? If you want various parts of your application to use the same object factory, then you organise your design around that. You shouldn''t use various mechanisms and design patterns to allow you to organise your design around an arbitrary rule taken from the solution domain.

Singletons Are Evil.



I use an object called "Application" that acts as a dynamic global space for storing data and providing one log file. I ***want*** this object to be unique as obviously the running program is "a whole one", thus I enforce this behaviour by implementing the Singleton design pattern inside the Application Class.

I frankly don''t see the flaw in such design. But I am opened to suggestions

If I need local dynamic global space, I designed a Session class which instances can be stored inside the Application Instance.

I should release theese classes this week-end on sourceforge (I have to supplement the demo using application so that it demonstrates the use of Session object too). Then you can see more clearly (I hope) what I''ve done and give me some feedback



----
David Sporn AKA Sporniket

Share this post


Link to post
Share on other sites
davidsporn, are you worried that you might forget and make two application objects by mistake?

just because you will only have one of something, doesn''t mean you have to enforce it.

although, saying that, murphy''s law says ''if there is more than one way to do something and one of those ways is catastrophic then someone will do it that way''

hmm...

Share this post


Link to post
Share on other sites
quote:
Original post by petewood
davidsporn, are you worried that you might forget and make two application objects by mistake?

just because you will only have one of something, doesn''t mean you have to enforce it.

although, saying that, murphy''s law says ''if there is more than one way to do something and one of those ways is catastrophic then someone will do it that way''

hmm...


I''m pretty sure I will not forget... at least during a few years.

But my intention is clearly to grant that whatever code is written, things like unintentional duplication will be detected at compilation time, so that one can detect that he tryed to use improperly the API.

Thus the enforcing.


----
David Sporn AKA Sporniket

Share this post


Link to post
Share on other sites
quote:
Original post by davidsporn
But my intention is clearly to grant that whatever code is written, things like unintentional duplication will be detected at compilation time, so that one can detect that he tryed to use improperly the API.

I''m also slightly suspicious your design might be suffering from what''s called the "God Class Problem". Obviously, there''s not enough information for me to tell that, but it''s worth a mention. In brief, the God Class Problem is something commonly created by programmers moving from action-oriented to object-oriented designs. Action-oriented designs are based around a centralised control mechanism, whereas OO prescribes distributing system intelligence amongst a number of different classes [1], with no one class being responsible for overall system behaviour. If you have classes in your system with names like Manager, Driver, System or such-like, it may indicate that you have a "God class". "Application" also sounds like it might be such a class but, as I say, it''s not possible to tell.

[1] my ever increasing skepticism of OO leads me to refute that such an aim is purely the preserve of OO, but still...

Share this post


Link to post
Share on other sites
quote:
Original post by davidsporn
But my intention is clearly to grant that whatever code is written, things like unintentional duplication will be detected at compilation time, so that one can detect that he tryed to use improperly the API.

quote:
Original post by SabreMan
I''m also slightly suspicious your design might be suffering from what''s called the "God Class Problem". Obviously, there''s not enough information for me to tell that, but it''s worth a mention. In brief, the God Class Problem is something commonly created by programmers moving from action-oriented to object-oriented designs. Action-oriented designs are based around a centralised control mechanism, whereas OO prescribes distributing system intelligence amongst a number of different classes [1], with no one class being responsible for overall system behaviour. If you have classes in your system with names like Manager, Driver, System or such-like, it may indicate that you have a "God class". "Application" also sounds like it might be such a class but, as I say, it''s not possible to tell.

[1] my ever increasing skepticism of OO leads me to refute that such an aim is purely the preserve of OO, but still...


I''ll try to explain, but it seems I fall in this case (btw, it''s the first time I hear about "god class"). The goal of the Application instance is to store data and give access to a log file, and thoose data and log file must be accessible from any point of the application.

Here is a quick example of typical use :

  
int main()
{
Application * app_inst = Application::Instance() ;

app_inst->rLog() << "Initialisation sequence begins" << std::endl ;

app_inst->rPropertyMap()["foo"] = "Hello world" ;
app_inst->rPropertyMap()["width"] = 1024 ;
app_inst->rPropertyMap()["height"] = 768 ;
app_inst->rPropertyMap()["bpp"] = GetUserDefinedBpp() ;

app_inst->rLog() << "Initialisation sequence continues" << std::endl ;

Screen my_screen = new Screen (app_inst->rPropertyMap()["width"], app_inst->rPropertyMap()["height"], app_inst->rPropertyMap()["bpp"]) ;

app_inst->rLog() << "Initialisation sequence finished" << std::endl ;

//...do stuff...


app_inst->rLog() << "DeInitialisation sequence starts" << std::endl ;

delete my_screen ;

app_inst->rLog() << "DeInitialisation sequence finished" << std::endl ;

return 0 ;
}


Note : I designed the property map to be able to store some primitive types as well as std::string as well as object pointers from my class hierarchy.


----
David Sporn AKA Sporniket

Share this post


Link to post
Share on other sites
quote:
Original post by davidsporn
I''ll try to explain, but it seems I fall in this case (btw, it''s the first time I hear about "god class"). The goal of the Application instance is to store data and give access to a log file, and thoose data and log file must be accessible from any point of the application.

A log file''s a reasonable candidate for being globally accessible, but I have to wonder about your global dumping ground for data. Why? I mean, from your example, what are "width" and "height" - the screen size, right? Why does the screen size have to be globally accessible? When you play a sound do you need to know the screen size? It appears that you are carrying out the semantic equivalent of this:

class Application
{
public:
// everything
};


I''ve been working on an application recently which began it''s life around 10 years ago, and it uses a similar scheme for storing supposedly global data. Unfortunately, the temptation for developers is to stuff a magic value in that area and then to pull it back out somewhere else, switching on the presence of and value of a particular field to perform some action. This means that the global data area has basically been used to evolve some bizarre protocol, and adding data into that area can often have seemingly unrelated side-effects, with no easy means of finding out what those side-effect will be. Yuck!

Share this post


Link to post
Share on other sites
quote:
Original post by SabreMan
what problems does it cause if you have more than one object factory?
What benefits would it give? Object factories provide functionality, not state, and stateless constructs are ideal for globalization. Two object factories of same type would behave identically (unless you use prototype factory or something special like that). I wouldn''t go passing Math-object around that provides me sin() and cos()-functions, since those are stateless, ''global'' operations. Similarly, I wouldn''t go passing around the object factory.

Share this post


Link to post
Share on other sites
quote:
Original post by SabreMan
A log file''s a reasonable candidate for being globally accessible, but I have to wonder about your global dumping ground for data. Why?


Well since one year or so I''ve played with DirectX tut, then Nehe tutorial, and I always ended up with an Application class storing some data that I decided "it has to be global !". Thus tuning this class I was obliged to implement a new field (btw it was *public* fields -yes you can shoot me, but at that time, good practices was not the point of my previous training, and I am sooo lazy...-)

On the other hand at work I''m a developping web sites and intranet applications and in environnement like theese (broadvision, jsp, ...), there is an Application object that can store the data that are globally accessible. There are also Session object that do the same for a user-session scope.

So I transposed this model to my API to have the same facilities.
(class Application and class Session)

quote:
Original post by SabreMan
I mean, from your example, what are "width" and "height" - the screen size, right? Why does the screen size have to be globally accessible? When you play a sound do you need to know the screen size?


I thought the same after posting, the exemple was not relevant as such values can be stored and retrieved using the hypothetically class Screen.... But the exemple was to show what the class could do.

*Maybe* I would store the Screen instance instead.

Another possible use I''ve just thought about is to store localised messages.

quote:
Original post by SabreMan
It appears that you are carrying out the semantic equivalent of this:

class Application
{
public:
// everything
};



That''s it. The point is that depending on the application, the "everything" is different. With my implementation I can go without rewrite a new dedicated Application class. This is my tribute to my Legendary Old Lazzyness (aka LOL ).


----
David Sporn AKA Sporniket

Share this post


Link to post
Share on other sites
quote:
Original post by civguy
What benefits would it give?

That's precisely the inverted logic that leads to unnecessarily creating singleton classes. You make something a singleton if the system requirements demand maximum one instance of an object, and if having more than one causes a genuine problem. "It doesn't make sense to have more than one" isn't a strong enough criteria. Making something a singleton creates complications, so there needs to be a positive reason to do it, not a negative force pushing in the other direction.
quote:

Object factories provide functionality, not state, and stateless constructs are ideal for globalization.

However, stateless constructs are not ideal as objects. I'm not sure where you've got your factory concept from. Factory is simply a means of virtualising object creation, and there is nothing about that which requires Singleton-like properties. So what if a user wants to create fifty class factories? That's their problem!

You might consider these snippets from some Python I wrote fairly recently:


    
from Meta import meta

# ... define exception classes ...

class Message(meta.ClassInitObject):
__messages = {}
def __classinit__(cls):
# uses a metaprogramming mechanism to populate __messages

def __init__(self):
assert 0 # class is abstract

# getClass is a class factory
def getClass(id):
try:
cls = Message.__messages[(id)]
return cls
except KeyError:
raise NoSuchMessage(id)
getClass = meta.static(getClass)

Usage would be:

  
try:
factory = Message.getClass((id, Message.REPORT))
# "factory" is now an object factory, but we never
# need to know the type of object it creates:
msg = factory(response.destructure())
except Message.NoSuchMessage, e:
# do exceptional processing
except Message.InvalidConstruction, e:
# do exceptional processing

I don't see any restriction that requires me to make Message a singleton just because it provides factory functionality. In fact, you can't even instantiate a single Message as it is an abstract class: it's meaningless to create *one* Message, let alone more than one.
quote:

I wouldn't go passing Math-object around that provides me sin() and cos()-functions, since those are stateless, 'global' operations.

If you're referring to Java's Math class, then that's simply an example of Java idiocy. The fact that the math operations have to be in a class is downright stupid.

Edit: fix tags.

[edited by - SabreMan on November 22, 2002 11:08:17 AM]

Share this post


Link to post
Share on other sites
How would one make pluggable factories without a singleton factory registry? I find the argument against the singleton compelling, but I can''t find a way around it in this case.

Share this post


Link to post
Share on other sites
quote:
Original post by SabreMan
That''s precisely the inverted logic that leads to unnecessarily creating singleton classes.
Not in my opinion. If there aren''t any benefits in not using a singleton (like, the class *could* have multiple instances in some other application), and singleton makes coding more convenient, then I wouldn''t hesitate to use one.

But, having said that, I must admit that object factory isn''t a place for a singleton pattern and I can''t come up with a good application for singleton right now. You may have won the fight, but the war isn''t over

Share this post


Link to post
Share on other sites
Would a class to handle the graphics in DirectX be an example of when to use a singleton? Having multiple render Devices would be very bad. Having global access to the render Device would allow each screen object to draw itself.

Share this post


Link to post
Share on other sites
quote:
Original post by civguy
Not in my opinion. If there aren''t any benefits in not using a singleton

There are many benefits in not using a singleton, like avoiding the problems intrinsic to singletons. Lifetime management? Singleton interpendencies? Have you read the reams of stuff written on those topics?
quote:

But, having said that, I must admit that object factory isn''t a place for a singleton pattern and I can''t come up with a good application for singleton right now. You may have won the fight, but the war isn''t over

You might come up with a single example (pun intended) of where singleton is relevant, but that wouldn''t prove any particular point. My point isn''t that there is no places where a singleton is relevant, it''s that many people have got their heuristic wrong for deciding on a singleton. What I''m trying to get at here is to move away from a "mechanical" way of thinking, which leads to inappropriate use of singletons. "I only want one of these, so I''ll use a Singleton" is mechanical - i.e. you''ve decided on a solution domain mechanism before really understanding the other design forces. Mechanical thinkers often create accidental complexity - that is, complexity that is not intrinsic to the problem being solved.

Note the subtle difference between there *is* only one of something, and there *can be* only one of something. If there is only one of something in the problem domain, then an abstract thinker would arrange the design around that idea so that you don''t have an artificial restriction to prevent accidental creation of a second instance. You don''t need to protect against it because it is not a case that exists in the world you are modelling.

Share this post


Link to post
Share on other sites