Manage Node Lifetime (OOP)
Manage Node Lifetime (OOP)
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!
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!
Re: Manage Node Lifetime (OOP)
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
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
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Re: Manage Node Lifetime (OOP)
Hello, thanks for the reply. Where you said the below:
Also creating methods such as "addMeshSceneNode" increment the counter by 1 meaning if I call addMeshSceneNode I do not call a grab?
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?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.
Also creating methods such as "addMeshSceneNode" increment the counter by 1 meaning if I call addMeshSceneNode I do not call a grab?
Re: Manage Node Lifetime (OOP)
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).
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
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Re: Manage Node Lifetime (OOP)
Fantastic, thanks. I was trying to combine both remove and drop, hence my confusion, make much more sense now.
Re: Manage Node Lifetime (OOP)
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:
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.
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;
}
};
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.
Re: Manage Node Lifetime (OOP)
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)
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)
Re: Manage Node Lifetime (OOP)
Thanks for your reply. By the below:
Instead of just a direct switch?
Then in terms of:
Do you mean implementing something along the lines of:devsh wrote:You need to drop the old value (if non-null) before changing the pointer "irrNodePntr = other. irrNodePntr;"
Code: Select all
If (irrNodePntr){
irrNodePntr.Drop();
}
irrNodePntr = other. irrNodePntr;
Then in terms of:
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.devsh wrote:so the very last drop, should really be a remove() (which will unparent and drop the node by its parent)
Re: Manage Node Lifetime (OOP)
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
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
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Re: Manage Node Lifetime (OOP)
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.
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.
Re: Manage Node Lifetime (OOP)
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
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Re: Manage Node Lifetime (OOP)
What will your IMeshSceneNode wrapper class do, and is it at all possible for it to out-live the IMeshSceneNode it wraps?