a question about singletons

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
stevend
Posts: 114
Joined: Sat Mar 01, 2008 7:18 pm

a question about singletons

Post by stevend »

well i have adopted the use of singletons for my factory in my game engine. it really makes alot of things easier.

i have started writing another small program for my own use, and it is using C. now, i was wondering,

with a singleton class you would do this to get its instance:

Code: Select all

myclass theSingleton = myclass::getinstance();
now i rememberd something from when i started with C. this is pretty much a singleton, but MUCH easier to implement.

definition

Code: Select all

struct myclass
{
    int somevar;
    void somefunction () { instance.somevar = 1; };

} instance; /* <-- */

and usage

Code: Select all

instance.somefunction ();
my question is, i have been flamed for using this coding technique before. i know it seems wrong coming from a C++ enviorment, but what is wrong with using this method? i don't see any issue other than sloppyness, but that doesnt matter in a project with minimal lines of code...

thanks!
strale
Posts: 119
Joined: Wed Nov 23, 2005 1:58 pm
Location: Lambrugo Italy
Contact:

Post by strale »

Hi

Code:
myclass theSingleton = myclass::getinstance();

i belive the correct call is
myclass * theSingleton = myclass::getinstance();
as you get a pointer to the single object


For the second point you are trying to make a class, not a singleton, a class has private information that a structure has not.

I remeber having read something about Bjarne Stoustrup that state a good C priogram tent to object oriented stile or something like.

anyway if you have c++ why force your progrms to have a look like c++ but without all the facilities of c++ and the standard stile of c++ ?

Cheers
torleif
Posts: 188
Joined: Mon Jun 30, 2008 4:53 am

Post by torleif »

The usage of :: in C++ accesses the name space, not a structure.

Code: Select all

myclass theSingleton = myclass::getinstance();
Should be

Code: Select all

myclass* theSingleton = new mynamespace::myclass();
theSingleton->somefunction ();

Code: Select all

namespace mynamespace
{
class myclass{
  public:
    int somevar;
    void somefunction () { instance.somevar = 1; };
  }
}
This will ensure your code is grouped together correctly (ie, using a math name space for math functions, or a unit name space for solder classes)

With C, there isn't much point in using singletons as structs don't support private variables
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Re: a question about singletons

Post by rogerborg »

stevend wrote:

Code: Select all

struct myclass
{
    int somevar;
    void somefunction () { instance.somevar = 1; };

} instance; /* <-- */
I'd imagine that it may annoy people because they wouldn't expect it to work, because AFAIKnew declaring "struct foo { } bar;" is just a handy shorthand for "struct foo { }; foo bar;", so it's not intuitive that the struct methods would know about and be able to refer to the instance of it.

It looks bizarre, but it does appear to work, at least on MSVC. Your milage may vary with other compilers though.

If you're trying to mimic a singleton, then using static members and methods might be a closer match:

Code: Select all

struct myclass
{
    static int somevar;
    static void somefunction()
    {
        somevar = 1;
    }
};

int myclass::somevar = 0;

// usage
myclass::somefunction();
strale wrote:a class has private information that a structure has not.
I'm not sure what you mean by that, but a class is a struct, and a struct is a class. The only difference is default access and inheritance.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
strale
Posts: 119
Joined: Wed Nov 23, 2005 1:58 pm
Location: Lambrugo Italy
Contact:

Post by strale »

Hi rogerborg
thankyou

I was wrong about beliving that in a structure was not allowed the "private:" statement

Code: Select all

struct Test{
      char cNpriv;
    private:
      char cPriv;
};
but i just realized ...it can be done!

bye
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

Oh, it gets funkier.

Code: Select all

// The default access in a struct is public, so MyStruct::Foo is public
struct MyStruct { int Foo; };

// A class can inherit from a struct.  The default inheritance is private
// so to keep Foo public, we have to specify public inheritance
class MyClass : public MyStruct { };

// And a struct can inherit from a class.  The default inheritance is public...
struct AnOtherStruct : MyClass { };

// ...so Foo percolates up as public, and this is valid.
AnOtherStruct instance;
instance.Foo = 99;
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
stevend
Posts: 114
Joined: Sat Mar 01, 2008 7:18 pm

Post by stevend »

yeah any mistypes was simply because:
Posted: Wed Aug 06, 2008 4:07 am
don't worry about why i need this, lets just say, i was curious

thanks rogerborg! and others
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

stevend wrote: with a singleton class you would do this to get its instance:

Code: Select all

myclass theSingleton = myclass::getinstance();
As pointed out by strale, the getinstance() static method would often return a pointer. Your code might look like this if myclass is a reference counted pointer to a implementation, but I don't see any motivation to do that.
stevend wrote: this is pretty much a singleton, but MUCH easier to implement.

Code: Select all

struct myclass 
{ 
    int somevar; 
    void somefunction () { instance.somevar = 1; }; 

} instance; /* <-- */ 
This is most definitely not a singleton. By definition, there can only be one instance of singleton type. I can easily create another instance of type myclass by writing

Code: Select all

myclass instance2;
Making the class anonymous (removing its name) won't fix the problem because you aren't allowed to declare an instance of a type with no linkage (an anonymous class) in a context where it has linkage.
torleif wrote: The usage of :: in C++ accesses the name space, not a structure.

Code: Select all

myclass theSingleton = myclass::getinstance();
No, :: is the scope resolution operator. In this case it is being used to invoke a static method of class myclass. It can also be used to tell the compiler to invoke a non-static method of a specific base class, like so...

Code: Select all

struct A
{
  virtual void foo ();
};

struct B : A
{
  virtual void foo ();
  void bar ()
  {
    A::foo (); // explicit call A::foo()
  }
};

int main ()
{
  B b;
  b.A::foo();
}
...or to access a nested class...

Code: Select all

struct A {
  struct B {
    static void f ();
    void g ();
  };
};

int main ()
{
  A::B ab;
  ab.g ();

  A::B::f ();
}
torleif wrote: Should be

Code: Select all

myclass* theSingleton = new mynamespace::myclass(); 
theSingleton->somefunction (); 
No. Again, this is not a singleton because you can create multiple instances. It is just a regular class that happens to be declared in a namespace.
rogerborg wrote: I'd imagine that it may annoy people because they wouldn't expect it to work... Your milage may vary with other compilers though.
Actually, it is completely legal C/C++.
rogerborg wrote: If you're trying to mimic a singleton, then using static members and methods might be a closer match...
That isn't a singleton either. It is a similar to a design pattern called the monostate. The method isn't usually static, but the data is static so that there is only ever one copy of the data (ignoring issues with static and shared libraries).

The advantage of a true singleton over the monostate is that the singleton will be lazy initialized. The monostate will be constructed in an undefined order (the static initialization problem), but the singleton will be constructed on first use. This may not be a problem in some cases, but it is something to keep in mind as use of a singleton type pattern often leads to use of many of them, and interdependencies between them can cause problems at program startup or shutdown.

Travis
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

vitek wrote:
rogerborg wrote: If you're trying to mimic a singleton, then using static members and methods might be a closer match...
That isn't a singleton either.
Point of order: nobody said that it was. :P

vitek wrote: It is a similar to a design pattern called the monostate. The method isn't usually static, but the data is static so that there is only ever one copy of the data (ignoring issues with static and shared libraries).
I prefer to make the methods static as well, since if there's no instance data, then there's no need to or benefit from creating an instance, and no need for any instance methods that might encourage doing so.

One of the things that I dislike about singletons is this:

Code: Select all

Singleton * foo = Singleton::getInstance();
Singleton * bar = Singleton::getInstance();
assert(foo == bar);
I can see very little point (pun ahoy!) in obtaining a pointer that will always have the same value and then calling an instance method on it, if the data can be static, and accessed through static members.

There's only an advantage if you want to delay instantiation of (singleton) instance data, which leads us to...

vitek wrote:The advantage of a true singleton over the monostate is that the singleton will be lazy initialized.
Indeed, but it's a dubious advantage, since...
vitek wrote:use of a singleton type pattern often leads to use of many of them, and interdependencies between them can cause problems at program startup or shutdown.
...which in practice can and in my experience does lead to ad hoc rules about when you can, can't and must instantiate singletons. In fact if you end up instantiating them in a fixed order early in startup in order to avoid problems, that seems to me to be a too-clever-by-half way of doing it all with statics, i.e. calling a explicit static instantiation method that initialises static members.

And the reason that I prefer doing that is that it's clearer. If you have to force initialisation, a method called initialise() is much more intellectually honest - and kind to maintainers - than hiding it behind an early call to a generic getInstance() method.

You may guess from this that I'm not exactly a raging fan of singletons. I think they're a very clever solution that can lead developers away from a dumb but simpler one. I like dumb and simple, because it's easier to pick up two years down the line.

However, I wouldn't want to get too... zealous about it. ;)
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
stevend
Posts: 114
Joined: Sat Mar 01, 2008 7:18 pm

Post by stevend »

vitek: i wrote the code failry early in the morning and i know i messed up something but ya know :lol:

any who, i understand the benefits of a singleton, and yes after some reading i understand why those should be static in this case,

to reword my question maybe this will make more sense...

what is wrong with this:

Code: Select all

struct myclass 
{ 
    int somevar; 
    void somefunction () { instance.somevar = 1; }; 

} instance; /* <-- */
other than the fact they should be statically declared or w/e, i have got my awnser

vitek:
Actually, it is completely legal C/C++.
..

i should stop posting at 4 am :P
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

rogerborg wrote: However, I wouldn't want to get too... zealous about it
Sorry about that. I tend to get a bit schizophrenic when I see well defined terms being used incorrectly. I did notice that you didn't call your code a singleton, I just thought I'd mention it isn't a real singleton since I was already making the point with the original code...

Travis
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

vitek wrote:Sorry about that. I tend to get a bit schizophrenic when I see well defined terms being used incorrectly.
You get auditory hallucinations, paranoid or bizarre delusions or disorganized speech and thinking? ;)

Well, there's always the option of a career in marketing.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Post Reply