[Solved] - Creating a SharedPtr to 'this'

Problems building or running the engine, queries about how to use features etc.
Post Reply
User avatar
PolyVox
OGRE Contributor
OGRE Contributor
Posts: 1316
Joined: Tue Nov 21, 2006 11:28 am
Location: Groningen, The Netherlands
x 18
Contact:

[Solved] - Creating a SharedPtr to 'this'

Post by PolyVox »

Hi, so I've started playing around with SharedPtrs in my application (I've never used them before) and I have a couple of questions...

1) Am I correct in thinking that, if I have a pointer to an object and I also create a SharedPtr to it, then if the SharedPtr goes out of scope the object is deleted and the original pointer is no longer valid?

2) If so the presumably pointers and SharedPtrs shouldn't be mixed. But what if you want a SharedPtr corresponding to 'this'?

My situation is as follows: I have a Volume class and a VolumeIterator class, and the VolumeIterator takes a SharedPtr to the Volume it operates over. But sometimes the Volume class wants to use a VolumeIterator within one of it's methods.

For example, the Volume class has a 'load' method. This reads data from disk and then uses a VolumeIterator to set the data (the Volume class is not capable of setting it's own data). This means the Volume wants to pass 'this' to the VolumeIterator. But, as I understand it, converting the 'this' to a SharedPtr means the Volume will now get deleted when the VolumeIterator does.

Perhaps my mistake is to make the Volume incapable of changing it's own data. This can be fixed but I'm then duplicating code between the Volume and the VolumeIterator.

Or perhaps there's some way to tell a SharedPtr not to delete the object it points at? I can manipulate it's count somehow? Sounds a bit messy....

Any thoughts appriciated!
Last edited by PolyVox on Fri May 11, 2007 3:34 pm, edited 1 time in total.
Oogst
OGRE Expert User
OGRE Expert User
Posts: 1067
Joined: Mon Mar 29, 2004 8:49 pm
Location: the Netherlands
x 43
Contact:

Post by Oogst »

I think the key issue you are overlooking is that the Volume itself has to be made somewhere. Someone already has a pointer to a Volume at the moment you pass this to the VolumeIterator. This pointer to the volume that already existed should be SharedPtr as well and would thus save the Volume from being destroyed if the VolumeIterator is removed.
My dev blog
Awesomenauts: platforming MOBA (PC/Mac/Linux/XBox360/X1/PS3/PS4)
Blightbound: coop online dungeon crawler (PC)
Swords & Soldiers: side-scrolling RTS (Switch/PS3/Wii/PC/Mac/Linux/iPhone/iPad/Android)
Proun: abstract racing game (PC)
Cello Fortress: mixing game and live cello performance
The Ageless Gate: cello album
User avatar
Project5
Goblin
Posts: 245
Joined: Mon Nov 22, 2004 11:56 pm
Location: New York, NY, USA

Post by Project5 »

Shared pointers and 'this' don't work well together, I'd recommend looking into boost::intrusive_pointer instead. Because the shared count is stored in the object instead of the pointer, you can mix shared and raw pointers freely without losing the reference count, the raw ones just act like weak pointers.

Hope that helps,

--Ben
User avatar
PolyVox
OGRE Contributor
OGRE Contributor
Posts: 1316
Joined: Tue Nov 21, 2006 11:28 am
Location: Groningen, The Netherlands
x 18
Contact:

Post by PolyVox »

Thanks guys, that's some excellent food for thought...
Oogst wrote:I think the key issue you are overlooking is that the Volume itself has to be made somewhere. Someone already has a pointer to a Volume at the moment you pass this to the VolumeIterator. This pointer to the volume that already existed should be SharedPtr as well and would thus save the Volume from being destroyed if the VolumeIterator is removed.
You are partly right, somewhere there will exist a SharedPtr to the Volume from when the Volume was created. But the problem is the Volume doesn't know about this - that is it doesn't know what pointers (shared or otherwise) point at it. The only thing it knows does point at it is 'this' - which is why I had been using 'this' to create a new SharedPtr...

But maybe I can give the Volume a new version of 'this' - a member which is a SharedPtr to itself. Actually, thinking about it, this would mean the Volume never gets deleted as the reference count is at least one. Hmmm...
Project5 wrote:Shared pointers and 'this' don't work well together, I'd recommend looking into boost::intrusive_pointer instead. Because the shared count is stored in the object instead of the pointer, you can mix shared and raw pointers freely without losing the reference count, the raw ones just act like weak pointers.
Ok, that sounds useful. I will look into boost::intrusive_pointer - the concept sounds like it makes sense. But there is a problem, this Volume is supposed to come from an Ogre::ResourceManager which will give a Ogre::SharedPtr. Maybe I can change that, or maybe there is a way to convert...

Any more ideas? Creating good designs is tough!
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Post by sinbad »

This depends a lot on ownership. I don't know the reason for your needing to pass 'this', but a common reason is to notify a child object of a parent. If that's the case, and the containment of the child is by value (ultimately - ie that the child will always be destroyed if the parent is), then it's ok to pass a 'this' provided that pointer is only ever referenced by the child. It sounds a bit hacky and conditional but it's actually a very common pattern.

If the object you want to pass 'this' to is a sibling or an object with an otherwise independent lifecycle it might be an indication of a bad design anyway, with cyclical dependencies. It's always good practice to try to make your dependencies unidirectional where possible except between objects which are already tightly coupled (like parent/child).
Oogst
OGRE Expert User
OGRE Expert User
Posts: 1067
Joined: Mon Mar 29, 2004 8:49 pm
Location: the Netherlands
x 43
Contact:

Post by Oogst »

esuvs wrote:...

But maybe I can give the Volume a new version of 'this' - a member which is a SharedPtr to itself. Actually, thinking about it, this would mean the Volume never gets deleted as the reference count is at least one. Hmmm...

...
Why would you want to use SharedPtr in the first place if you do not ever want to automatically delete your object? If the object itself always keeps a SharedPtr to itself, then the SharedPtr will never reach a zero count, so it will never be destroyed by the SharedPtr.
My dev blog
Awesomenauts: platforming MOBA (PC/Mac/Linux/XBox360/X1/PS3/PS4)
Blightbound: coop online dungeon crawler (PC)
Swords & Soldiers: side-scrolling RTS (Switch/PS3/Wii/PC/Mac/Linux/iPhone/iPad/Android)
Proun: abstract racing game (PC)
Cello Fortress: mixing game and live cello performance
The Ageless Gate: cello album
User avatar
PolyVox
OGRE Contributor
OGRE Contributor
Posts: 1316
Joined: Tue Nov 21, 2006 11:28 am
Location: Groningen, The Netherlands
x 18
Contact:

Post by PolyVox »

Oogst wrote: Why would you want to use SharedPtr in the first place if you do not ever want to automatically delete your object? If the object itself always keeps a SharedPtr to itself, then the SharedPtr will never reach a zero count, so it will never be destroyed by the SharedPtr.
I wouldn't, I was just thinking aloud... hence the "actually this doesn't make sense" part. And that's what I've now realised based on what you and Sinbad said - there is no real need for the VolumeIterator to hold a SharedPtr, it can (and should) just hold a regular one. The VolumeIterator shouldn't be responsible for destroying the Volume.

I guess I was just introducing SharedPtr's to the code and intuitively thought they should be used everywhere. But that's not really true...

Anyway, it's sorted now :)
Post Reply