Jump to content
  • Advertisement

Archived

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

rick_appleton

Sort of an alternative to singletons

This topic is 5200 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
Advertisement
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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!