Irrlicht Application Hub Class

A forum to store posts deemed exceptionally wise and useful
Post Reply
saigumi
Posts: 921
Joined: Fri Aug 22, 2003 11:31 am
Location: St. Louis, MO USA
Contact:

Irrlicht Application Hub Class

Post by saigumi »

Link - http://www.saigumi.net/pivot/entry.php?id=19

/*******************************************************************************

Hub by Frank Taylor(Pharoseer) and John Goewert(Saigumi)

This is a singleton-style class that creates one instance of the hub.
Instead of passing around variables from class to class, all
you need to do is get the instance of the hub.

The first time the Hub instances is gotten, it will create an Irrlicht
device. Consecutive getInstance() calls will return the Hub instance's
pointer.

Usage:

#include "hub.h"

Hub* my_hub = Hub::getInstance();


Do NOT pass "my_hub" to another class. Instead, just use the same code to get
the instance of the class.

Each of the public pieces are controlled by accessor functions, so be sure to
include the braces ().

Example:

irr::scene::IAnimatedMesh* mesh =
my_hub->irr_scenemgr()->getMesh("sydney.md2");


Also, you can add any other core classes that you need into the hub, not
just Irrlicht ones. This will save you having to pass around a bunch of
pointers and allow any piece of your application to access shared resources.

*******************************************************************************/
Crud, how do I do this again?
etcaptor
Posts: 871
Joined: Fri Apr 09, 2004 10:32 pm
Location: Valhalla
Contact:

Post by etcaptor »

Nice, will try it. Thanks! :lol:
ImageImage
Site development -Rock and metal online
--- etcaptor.com ------freenetlife.com
jox
Bug Slayer
Posts: 726
Joined: Thu Apr 22, 2004 6:55 pm
Location: Germany

Post by jox »

A singleton class is a great thing. Makes everything much more flexible.

Saigumi, one thing I noticed, already a while ago, in your implementation is that your (only) getInstance takes 7 parameters with default values. I was askin myself right away: isn't that adverse because those parameters get always pushed on the stack, even though they are omitted in the normal program flow? Then I forgot about it...

Now that I'm doing some profiling and analysis on assembler level (compare how certain C++ implementations compare to others) I remembered your Hub class and became curious. :)

I added another getInstance to your class that takes no parameters: getInstance2(void). Now in assembler these compare like this:

(Compiled with MSVC .NET under XP Pro)

Hub::getInstance() (original, 7 defaulted parameters)

Code: Select all

	push        0    
	push        0    
	push        0    
	push        0    
	push        10h  
	lea         ecx,[esp+30h] 
	push        ecx  
	push        4    
	mov         dword ptr [esp+38h],320h 
	mov         dword ptr [esp+3Ch],258h 
	call        Hub::getInstance (4010D0h) 
Hub::getInstance2() (void param)

Code: Select all

	call        Hub::getInstance2 (401170h) 
Quite some overhead. Using this often in tight loops might sum up.

Next step in optimizing would be declaring it inline (then there won't be even a call to getInstance).

Hub::getInstance2()->irr_driver()->getFPS() results in:

Code: Select all

	mov         edx,dword ptr [Hub::m_instance (40BA20h)] 
	mov         ecx,dword ptr [edx+4] 
	mov         esi,dword ptr [eax+4] 
	mov         eax,dword ptr [ecx] 
	add         esp,38h 
	call        dword ptr [eax+98h] 
I've also done a comparison of (f32, f32, f32) vs. (core::vector3df) with some benchmarking that I will maybe post later in the other thread where this has been discussed.

I'm not sure if this is really the best place for optimizing, and it's prolly also not recommended to use getInstance in tight loops but it's fun and insightful anyhow. :)
It is like it is. And because it is like it is, things are like they are.
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

It's fun reading things I only wish I could understand...

I have a question if it can be answered simply...

What is this for?

I'm interested to learn.
saigumi
Posts: 921
Joined: Fri Aug 22, 2003 11:31 am
Location: St. Louis, MO USA
Contact:

Post by saigumi »

Optimization of code for reduced overhead and speed.

Inlining is a possibility, but the downfall is that it replicates the code as many times as you call it in your compiled binary. Speed vs. Size.

I've been flipping through two books right now:Efficient C++: Performance Programming Techniques, which is awesome for lots of tips in working out performance and a great guide for STL methods, and Joel On Software, which has more to do with project management, but has a great set of tips on optimizing as well.

Since getInstance would be called by every object needing to talk to the hub, it is definitely something to look at improving. On the downside, improving it for one type of usage can cause performance issues in another.

I see what you mean about the blank getInstance call though. Since I was just using default loading as a way to handle a call with no parameters, I didn't realize that the default parameters still get stacked as if they were passed in.
Crud, how do I do this again?
keless
Posts: 805
Joined: Mon Dec 15, 2003 10:37 pm
Location: Los Angeles, California, USA

Post by keless »

Sai, dont forget the disadvantages of using a singleton:
* cannot be sure when it will be initiated
* cannot be sure when it will be destroyed
* cannot be sure who will use it
a screen cap is worth 0x100000 DWORDS
stodge
Posts: 216
Joined: Fri Dec 05, 2003 5:57 pm

Post by stodge »

That depends. If you have a singleton tha contains a static instance variable:

Code: Select all

private:
    static MySingleton* mInstance;
And also:

Code: Select all

public:
    static MySingleton* GetInstance();
Then presumably your singleton will get created when you first retrieve it:

Code: Select all

MySingleton* MySingleton::GetInstance()
{
    if (MySingleton::mInstance == NULL)
    {
        MySingleton::mInstance = new MySingleton();        
    }

    return MySingleton::mInstance;
}
If you have:

Code: Select all

private:
    static MySingleton mInstance;

Code: Select all

public:
    static MySingleton& GetInstance();
Then the singleton will get instantiated before main() is called.

Code: Select all

MySingleton& MySingleton::GetInstance()
{
    return MySingleton::mInstance;
}
At least that's my understanding.
keless
Posts: 805
Joined: Mon Dec 15, 2003 10:37 pm
Location: Los Angeles, California, USA

Post by keless »

yes, however you dont have a method to be sure when it will first be instanced. Someone else can come play with your code and add a call earlier than what you expected.

Furthermore, while you can assume it gets destroyed at the end of your application, you cant assume in what order with respect to other singletons (importantly: with respect to other systems it may be reliant on)

I dont mean to say this is neccesarily bad in your case. Just wanted to make sure you weighed the cost.
a screen cap is worth 0x100000 DWORDS
evolutional
Posts: 16
Joined: Mon Apr 11, 2005 2:32 pm
Location: LEEDS, England
Contact:

Post by evolutional »

keless wrote:Sai, dont forget the disadvantages of using a singleton:
* cannot be sure when it will be initiated
* cannot be sure when it will be destroyed
* cannot be sure who will use it
Definitely. I used Singletons in my games for a couple of years and often found that their use encouraged laziness and spaghetti-code. It has taken me a year to 'break' the habit and get my code back to how it should be. If you're tempted to use a Singleton because of the convenience factor, please take some time to ensure that it is what you need and not just a 'quick hack' to do what you need. Your code can and will suffer if you misuse Singletons.
Post Reply