Manage Node Lifetime (OOP)

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
TestDev
Posts: 11
Joined: Tue Jun 19, 2018 3:15 pm

Manage Node Lifetime (OOP)

Post by TestDev »

Hello All,

One of the things that I was unable to pick up from the tutorials is how to dispose of a node once I am done with it. Reading through the references has shown me the remove methods which to a beginner sounds like the place to go.

Now I am going down the route of OOP (Object-oriented Programming) and as such have created a class that will (in part) manage a Irrlicht scene node.

I was going to have my class hold a pointer to the Irrlicht node then implement the lifetime, so far I was going to add a constructor including the addMeshSceneNode method and then a deconstructor with remove. Then I was going to look towards building the rule of 3/5.

However when reading the references I found methods such as grab and thought that as this must be a very standard and probably trivial problem, is there anything built into Irrlicht to help manage the lifetime or any recommended patterns to do this with. I am sure there are a few ways of doing this but I was just wondering if there was anything tried and true in relation with Irrlicht.

Thanks for reading!
CuteAlien
Admin
Posts: 9646
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Manage Node Lifetime (OOP)

Post by CuteAlien »

grab()/drop() are about adding/releasing a reference counter. When counter is 0 then the object-memory is released. So that's usually what you do in your code when you have a pointer - grab() it until you no longer need it - then drop(). You don't think about releasing memory, but only about - this specific object no longer needs this pointer. And once no one needs it anymore the memory will be released.

The ISceneNode::remove() is not really about the memory management but about the SceneManager. You tell the scenemanager to remove that node from the scenegraph. Now if you don't have the node grab()'ed anywhere else - in this case this will also release the memory as the SceneManager willl internally use grap()/drop() as it uses the pointer. And once it calls drop() and no-one else grab()'ed the reference counter hits zero. But that's just a side-effect - the main reason for remove() is only to remove the node from the SceneManager object. For example you might have added it to another SceneManager before in which case the node-memory will be fine.

Note that sometimes people are lazy and don't grab()/drop() at all themself and regard any pointers they have themself as weak-pointers. Aka - they trust the memory will be there as they only add nodes to scenemanager, never release them ever (except maybe at program end). Which works fine for tiny applications, but isn't really good style.

The documenation for this is at http://irrlicht.sourceforge.net/docu/cl ... unted.html
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
TestDev
Posts: 11
Joined: Tue Jun 19, 2018 3:15 pm

Re: Manage Node Lifetime (OOP)

Post by TestDev »

Hello, thanks for the reply. Where you said the below:
CuteAlien wrote:You don't think about releasing memory, but only about - this specific object no longer needs this pointer. And once no one needs it anymore the memory will be released.
I just wanted to clarify if I correctly grab and drop the reference (pointer) as I go through the code then the Irr engine will take care of freeing up the memory and scene graph ect? I.E by using Grab and Drop there is no need to use remove or any other members?

Also creating methods such as "addMeshSceneNode" increment the counter by 1 meaning if I call addMeshSceneNode I do not call a grab?
CuteAlien
Admin
Posts: 9646
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Manage Node Lifetime (OOP)

Post by CuteAlien »

When the reference counter reachs zero then the object memory is released.
A function like addMeshSceneNode will internally grab() and ISceneNode::remove() will drop(), so if no one else did a grab() the object memory will be deleted at that point.

Note that Irrlicht also has caches for textures und meshes. So you remove the memory for the nodes, but not for the textures and mesh-geometry used in those nodes. If you want to clean the caches you have to do that explicitely (using the cache classes IMeshCache for caches and IVideoDriver for textures).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
TestDev
Posts: 11
Joined: Tue Jun 19, 2018 3:15 pm

Re: Manage Node Lifetime (OOP)

Post by TestDev »

Fantastic, thanks. I was trying to combine both remove and drop, hence my confusion, make much more sense now.
TestDev
Posts: 11
Joined: Tue Jun 19, 2018 3:15 pm

Re: Manage Node Lifetime (OOP)

Post by TestDev »

I have been trying to implement the Lifetime management, however my code is not working as expected. I keep hitting a debug error of having a reference counter less than 1 so I am not sure how this happens. So far my simplified code is:

Code: Select all

Class node{
    irr::scene::IMeshSceneNode* irrNodePntr = nullptr;
public:
    node(){}
    node(Params){
        irrNodePntr = smgr->addMeshSceneNode(Params);
    }
    ~node(){
        If (irrNodePntr){
            irrNodePntr->Drop();
        }
    }
    node (const node& other{
        irrNodePntr = other. irrNodePntr;
        irrNodePntr->Grab();
    }
    node& operator=( node other){
        irrNodePntr = other. irrNodePntr;
        irrNodePntr->Grab();
        return *this;
    }
};
 
So in short when creating the object I take a pointer to it.
Then whenever I copy the node I grab to increase the reference counter, then when deleting I drop the object.

My theory is that no many how many times I copy the reference counter should only hit 0 once the last object is done with. The only complexity is the need for my empty constructor, so to get around this I have set the pointer to 'nullptr' and just added an "if" guard in the deconstructor.

If you can spot any obvious errors please let me know or if there is anywhere else I can look please let me know.
devsh
Competition winner
Posts: 2057
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Re: Manage Node Lifetime (OOP)

Post by devsh »

You need to drop the old value (if non-null) before changing the pointer "irrNodePntr = other. irrNodePntr;"

The node's parent (even if you specified null, the parent is still the root scene node which incidentally is the ISceneManager) has its own grab reference simply by the virtue of the node being in the scene-tree, and every node in the tree will eventually get dropped when the tree is "destroyed" (every node calls removeChildren upon destruction).

so the very last drop, should really be a remove() (which will unparent and drop the node by its parent)
TestDev
Posts: 11
Joined: Tue Jun 19, 2018 3:15 pm

Re: Manage Node Lifetime (OOP)

Post by TestDev »

Thanks for your reply. By the below:
devsh wrote:You need to drop the old value (if non-null) before changing the pointer "irrNodePntr = other. irrNodePntr;"
Do you mean implementing something along the lines of:

Code: Select all

If (irrNodePntr){
    irrNodePntr.Drop();
}
irrNodePntr = other. irrNodePntr;
Instead of just a direct switch?

Then in terms of:
devsh wrote:so the very last drop, should really be a remove() (which will unparent and drop the node by its parent)
How can I ensure that drop is a remove? Would I have to reference the underlying counter in my deconstructor and if the reference value = 1 then remove else just drop? Not sure if there is a more elegant solution build into IrrLicht.
CuteAlien
Admin
Posts: 9646
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Manage Node Lifetime (OOP)

Post by CuteAlien »

You shouldn't really mix memory management with adding/removing stuff from the scenemanager. Nothing against writing a smart-pointer class, but don't mix in the call to addMeshSceneNode in there.
I wrote a simple smart-pointer class once for Irrlicht, maybe take a look: https://bitbucket.org/mzeilfelder/irr-p ... /irr_ptr.h
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
TestDev
Posts: 11
Joined: Tue Jun 19, 2018 3:15 pm

Re: Manage Node Lifetime (OOP)

Post by TestDev »

Ok, so stepping back for a bit I am thinking that my initial approach is flawed. I wanted to have my own "node" class that held a pointer to an "IMeshSceneNode" and would wrap up some functions for me.

So now I am thinking that this approach my be slightly off. How would you suggest that I control the lifetime of this "node" and the underlying IMeshSceneNode. Would it be best to have some sort of smart pointer in the node class, and to handle the creating and deleting separately.

Although this is where I come unstuck, any suggestions for this would be appreciated.
CuteAlien
Admin
Posts: 9646
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Manage Node Lifetime (OOP)

Post by CuteAlien »

That depends on your project. In most cases you just put a pointer to your nodes in whatever class needs them. For example a "Level" class might have some node pointer. And maybe 1-2 nodes in your "Player" class. No need really to add additional layers.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
devsh
Competition winner
Posts: 2057
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Re: Manage Node Lifetime (OOP)

Post by devsh »

What will your IMeshSceneNode wrapper class do, and is it at all possible for it to out-live the IMeshSceneNode it wraps?
Post Reply