Archived

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

Sort of an alternative to singletons

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

I've been working on my engine and other projects for a time now, and I've noticed that I've been using a kind of alternative to singletons quite a few times. Take for instance a logging implementation. Obviously this would be a prime candidate for singleton, since you'd only ever want one. What I've done, is put the class into the .cpp file of the logger, and exposed certain functionality as common (non-meber) functions. The headers are in the .h file for the logger, and the implementation in the .cpp file. By having a static variable of the logging class in that file, all the logging functions can use it, but it is hidden from the outside world. I guess this could also be achieved without using classes at all, but using a class here ensure that the file is opened an closed during construction/destruction of the static object. I realize that this wont always work since you'd need to control the initialization process sometimes, but then you can do the same, just call an Init function before using the normal funtionality. What do you think of this type of coding? [edited by - rick_appleton on April 21, 2004 11:04:18 AM]

Share this post


Link to post
Share on other sites
I use static variables for my memory manager class. The memory manager class is simply 3 static functions. Those functions use static variables inside in the .cpp file. I route new and delete to the static alloc/realloc/dealloc functions. The memory manager''s alloc/realloc/dealloc functions are static for non-new/delete allocations.

This isn''t really a singleton because I can easily just create a new memory manager object. If I do, the engine will most likely crash since all instances of that class will manipulate the same static variables.

I only used a static variable so memory manager construction/destruction will happen at the right time. Down side to this is that I can''t have ANY global variables that will allocate memory when they are created.

Intro Engine

Share this post


Link to post
Share on other sites
This is a system I would imagine a lot of people have made use of in the past. I myself have done the same, however it does posses one major down side which I tend to try to avoid in a lot of my more recent work.

When creating code which is intended to be memory efficient, or even code that may be reused in other project (modularity), creating static variables will indefinatly force that object to be linked and use memory at all times during the applications execution, even if the user just wants access to the class (not to treat it as a singleton).

A more robust solution perhaps would be to export a series of C-like functions which take care of creating and destroying the object. You do not have the benefits of automatic object destruction here, but a simple function placed at the end of your application to check maybe a reference count, or an object pointer (that it is non-NULL) will let you know if the object is being leaked. You do, however, gain the benefit of creating the object singleton only when it is needed, and when multiple resources need it, manage a reference count and pass the interface pointer to whatever code component is requesting access to the singleton, kind of like a COM object, and when the object is not in use, it can be unloaded from the memory to free resources for other purposes. Also, if you decide to reuse part of this code in other project, you do not actually have to construct the singleton object by not using a static variable.

Anyway, just a thought.

Share this post


Link to post
Share on other sites
That method is actually quite common. If you want to minimize memory usage (if its ever left unused), keep a static pointer. I''ve seen pretty competent people(read experieced s/w professionals) use that exact method (I dont use it myself tho), so youre in good company.

Share this post


Link to post
Share on other sites
That''s not really a place for a singleton anyways. You use a singleton when you want to guarantee there can and will exist only one, not when you only want one. I see no reason to make such a restriction on a logging class - I can even think of a few instances where several might be preferable.



[My site|SGI STL|Bjarne FAQ|C++ FAQ Lite|MSDN|Jargon]
Ripped off from various people

Share this post


Link to post
Share on other sites
Warning: Java rant follows.

I tend to do things with all static members - functions and data. Avoids all that messy getInstance() stuff however you choose to implement it. However, I''m working in Java, which seems not to have those annoying static-order-of-initialization issues - or at least I''ve never built anything complicated enough to have to worry about them. In Java AFAICT classes are loaded the first time they are referenced at runtime; and you can have static initializing code - and IIRC static finalizers too, though I haven''t needed such things.

IMHO this is the best way to do things if you can get away with it, because you''re using the language''s natural, built-in mechanism for "there is only one instance of this bit of data for the whole class". Why wrap my data up in an object instance, and jump through hoops to preserve its singularity, when I can just wrap it into the class definition? (I like to think of it as being wrapped into the Class object that represents the class - but Class objects are again a Java idiom, and it''s not really true anyway, since going through the class object to get at those fields would require reflection.)

I am rather irritated by how extensively the Java library uses the Singleton pattern - it''s like they fixed problems in C++, and then blindly applied unneeded workarounds to those problems because the GoF book told them to. :/ Especially bad is (for J2ME at least) "this.getClass().getResourceAsStream(String)". Given that it doesn''t matter which class "this" is, why do I need a Class object to get at this functionality - why shouldn''t I just write "Class.getResourceAsStream"? Oh, but statics are eeeeevil, they say (and pay no attention to the java.lang.Math behind the curtain!)...

Share this post


Link to post
Share on other sites
quote:
Zahlman:
Why wrap my data up in an object instance, and jump through hoops to preserve its singularity, when I can just wrap it into the class definition?
In Java, objects give you polymorphism.

Share this post


Link to post
Share on other sites
Well I use singleton objects throughout my code; in order to minimize the actual stuff I need to write... ie: cLog::GetClass().SomeFunction();

I just use macros, LOG.SomeFunction();

#define LOG cLog::GetClass()

Of course the logger is the easiest and doesn't requrie much typing at all, but with namespaces, and other layers such as video (and an factory interface for dlls) it makes it much easier.

--
j dot bellone at flipsidesoftware dot com
FlipEngine Development Site

[edited by - bkt on April 22, 2004 12:19:55 PM]

Share this post


Link to post
Share on other sites
A slight difference that I''ve also done is to have in the class in the header file, and have it initialised just like a singleton, but have a static pointer to it in the .cpp file. Then have an ''extern ....'' also in the header, so all files can get to it.

Share this post


Link to post
Share on other sites
As said previously, for a logging class it makes sense for it to be a regular class and not a singleton because you might want multiple logs for different parts of the engine(maybe one for the init/deinit part of the engine, one for logging gameplay events, etc).

Also, any half-decent implementation of a log class would''nt keep the file open the whole time. What good does it do to log things if, when your program crashes, nothing is actually written to disk? At the very least you need to flush it to disk after every write to make sure it actually helps with debugging.

Share this post


Link to post
Share on other sites
quote:
Original post by civguy
quote:
Zahlman:
Why wrap my data up in an object instance, and jump through hoops to preserve its singularity, when I can just wrap it into the class definition?
In Java, objects give you polymorphism.


How is polymorphism at all meaningful or useful for an object that I only want one of?

Share this post


Link to post
Share on other sites
quote:
Original post by Zahlman
How is polymorphism at all meaningful or useful for an object that I only want one of?

Singletons are often implemented polymorphically. As a simple example, consider a "Renderer" singleton, which may be either an OpenGLRenderer or a DirectXRenderer. You only want one Renderer, and you want to decide at runtime which one it is.


"Sneftel is correct, if rather vulgar." --Flarelocke

Share this post


Link to post
Share on other sites
quote:
Original post by Sneftel
quote:
Original post by Zahlman
How is polymorphism at all meaningful or useful for an object that I only want one of?

Singletons are often implemented polymorphically. As a simple example, consider a "Renderer" singleton, which may be either an OpenGLRenderer or a DirectXRenderer. You only want one Renderer, and you want to decide at runtime which one it is.


"Sneftel is correct, if rather vulgar." --Flarelocke


Aha. Haven''t needed it yet. At least, not for something that I couldn''t just init() at runtime. I suppose for OGLRenderer versus DXRenderer you''re going to be looking at different code for the various functions though, and if-ing everything would be decidedly hairy.

Of course, I suppose there''s always the option, instead of having getInstance() in the base Renderer, of having static delegate methods? (i.e. a whole bunch of stuff like "static void drawThing() { instance->drawThing(); }") Though if you also need the lazy instantation, that adds up to a lot of duplication pretty quickly. :/

Share this post


Link to post
Share on other sites
quote:
Original post by Zahlman
Of course, I suppose there''s always the option, instead of having getInstance() in the base Renderer, of having static delegate methods? (i.e. a whole bunch of stuff like "static void drawThing() { instance->drawThing(); }") Though if you also need the lazy instantation, that adds up to a lot of duplication pretty quickly. :/

Well, sure. But what that represents is that delegates are really just interfaces with a single method. In this case, it''s the wrong tool for the job, since it implies a flexibility that does not actually exist. For instance, if you had the methods DrawObject and LoadTexture, It would be technically possible for the static delegates to refer to OpenGL''s DrawObject and DirectX''s LoadTexture, which would be an error. Also, keep in mind that such a singleton would have not only methods, but also variables. For instance, DirectX will need a Direct3DDevice, while OpenGL will need a HGLRC. These are packaged up nicely with the methods through the singleton method. For simpler situations, of course, a static delegate may be just what the doctor ordered.


"Sneftel is correct, if rather vulgar." --Flarelocke

Share this post


Link to post
Share on other sites