SmartPointer (aka Handle) question

in Help Center
Hi,
I wanted to know if it's legal to pass 'this' to a constructor/function which expects a Handle?
How will it determine it's referencecount? Because to me it looks like:
- pass *this*
- incRef [ ref = 1 ]
- ... do something
- decRef @ destructor of Handle [ ref = 0 ]
- --> destroy *this*
Which ofcourse isn't good as I just passed *this* expecting it would survive the Handle.
What I also experienced is that when I'm working in a function called remotely (proxy->function), if I pass *this*, where *this* is the proxy I'm working on... It's not a problem at all... It increases nicely (the reference count) and decreases nicely, but never gets to 0, so it's not destroyed...
But if I just do it completely locally in a Handle, it will increase to 1, and decrease to 0, destroying the *this* object...
Could you give me any pointers on how to interpret this powerfull feature of SmartPointers in ICE?
Thanks a lot!
I wanted to know if it's legal to pass 'this' to a constructor/function which expects a Handle?
How will it determine it's referencecount? Because to me it looks like:
- pass *this*
- incRef [ ref = 1 ]
- ... do something
- decRef @ destructor of Handle [ ref = 0 ]
- --> destroy *this*
Which ofcourse isn't good as I just passed *this* expecting it would survive the Handle.
What I also experienced is that when I'm working in a function called remotely (proxy->function), if I pass *this*, where *this* is the proxy I'm working on... It's not a problem at all... It increases nicely (the reference count) and decreases nicely, but never gets to 0, so it's not destroyed...
But if I just do it completely locally in a Handle, it will increase to 1, and decrease to 0, destroying the *this* object...
Could you give me any pointers on how to interpret this powerfull feature of SmartPointers in ICE?
Thanks a lot!
0
Comments
Without the calls to __setNoDelete(), the reference count would become zero after the call to some_function(), and the Foo object would destroy itself.
But what if you have a class like:
Where 'this' points to a class 'House' for example.
Where would you put the __setNoDelete functions then? Because I guess from the code you've written it's some kind of global don't delete function...
The Handles, do they work based on the pointer? For example an internal mapping from pointer -> reference count, or is it stored in the object itselves GCShared?)?
Maybe the previous example is just a bad design, it's possible ofcourse...
Maybe a little more indepth example picturing the structure of my project:
- I have a Factory
- It create()'s Car*'s
- Inside the Car you can have - for example - seats: CreateSeats( color, ..., CarPtr );
Now there the problem arises... Because I want to be able to return from a seat to it's car, i need some way to do it... I did it by having a function in the Factory keeping track of every car made, and whenever a SeatI is constructed, I call the Factory to ask... Please give me the Car with this identification number. Then the Factory will provide me with a CarPtr, which I pass through the Seat-constructor.
I can feel it in my guts this is absolutely wrong design, but I really have no idea how to implement the Car* getParent() function otherwise...
That's where I used to use 'this' instead of the call to the Factory... And that's where it used to crash untill I figured out it was because the reference count dropped 0 sometimes... Because if you destroy a Seat, the reference count for the "Handle<Car> _parent" becomes 0, destroying the object Car, which ofcourse is not correct as it might have still other things in there...
Thanks if you could clarify me what I should use to counter this kind of 'parent'-question.
I'm afraid I don't understand the question. Why would you need the __setNoDelete function in the code above?
__setNoDelete is not a global function, it's a member function of the base class for reference counted objects.
It is stored in GCShared. This is called "instrusive reference counting".
Let me suggest that you provide a concrete code example instead of explaining the problem, then I tell you how to solve the problem
Slice definitions (highly simplified):
Implementation:
That's basically it... And this is what bothers me (although it works fine):
--
SeatPtr seat = new SeatI( parent.GetMyPrx(m_ID) );
--
Hope you know a better way of doing it
Greetz,
However this is of very little concern to me
Thanks,
Global or not, you must not create servants or other reference-counted objects on the stack, and you should always refer to them using a handle, not a C++ reference. Otherwise it's easy to screw up the reference count.
I still don't understand... what exactly is not properly done in this function?
But if I change my source like:
And then I pass '*this' to the constructor... Won't the FactoryPtr reference count be increased to 1 upon assignment inside the CarI-constructor? And won't it be dropped to 0 upon destruction? But I guess that I should be useing something like the __setNoDelete(true) then.
Why I say not properly done is because it looks like not very "neat" to me... Like maybe you know some easier way to do it then to keep a mapping of some ID and related proxies inside the main Factory. I was more thinking of something like some kind of internal function or some way to pass *this* to the SeatI-constructor without actually destroying the CarI upon destroying the SeatI.
Could you tell me if this would have that effect:
Because if I can do this way, I create a new CarPtr, with *this*, which won't get destructed upon destroying SeatI.
I also saw you were setting it back to false, but if I never want it to be destroyed (*this* shouldn't be destroyed by the Handle), then I can just leave it like that right?
Why? You store the parent in a handle, which increases the count. Nothing will get deleted. No calls to __setNoDelete() are necessary.
Can you show me the concrete code that passes "this" and causes the destruction?
Sorry, I'm afraid I still can't follow you. Please show me a simple code example that causes a crash if "this" is passed. Make the example self-contained, don't allocate servants on the stack, use handles and no C++ references, and mark exactly the place where it crashes. Otherwise it is very difficult for me to help you.
I once made a test program which crashed upon such thing as we're talking about here now... I still had that in my mind.
So I was trying now to recreate it, but seems to miserably fail to do it.
Probably it was a mix of C-pointer, C-references and Ice-handlers... Right now I did this:
Having the "public IceUtil::Shared" commented, it will give an error of not finding __*ref functions.
So I really don't remember how I did it, but seems like if I make every object via slice (so basically going back to Ice::Object & Ice::GCShared), it will have a reference counting, and passing a *this* won't cause ANY problems at all
Which answered my question, and might shed some light on why I was still pursuing the wrong idea that passing a *this* could cause improper pointer deletion.
Thanks for your patience Marc!