Paul Martz <[EMAIL PROTECTED]> wrote:
>There's no confusion. If your object is derived from
>osg::Referenced, then osg::ref_ptr owns it.
No, it's not that simple, because of how OSG API was designed.
It really is that simple. If the object is derived from Referenced, it's
destructor (with very few exceptions) is protected. So, the only code that
could possibly be responsible for owning (and deleting) that memory is a
ref_ptr. If you are keeping a regular pointer to that object, and you think
you own it, then you are mistaken, because not only can you not delete it,
but it can (and usually will) be deleted out from under you, leaving you
with a dangling pointer.
Geode is derived from Referenced.
A Geode can be put into a ref_ptr.
But the app can only pass a Geode to Group::addNode(Node*)
as a raw pointer.
Correct. And at that point, Group assigns a ref_ptr to that memory.
By "pass", I mean a hand-off to OSG --
the app is done using it. But OSG still has the Geode
after addNode() returns. Then when removeNode() is called,
should or shouldn't OSG delete the Geode?
At that point, OSG will remove its ref_ptr to that Geode, which decrements
the ref count. If the ref count reaches zero, the object deletes itself.
What if the app was still using it?
But that app is NOT still using it, you just said so yourself above. You
wrote: "the app is done using it". If that app IS still using it, then the
app should keep a ref_ptr to it. And in that case, the ref count would not
drop to zero, so the memory wouldn't be deleted..
Those questions a ref_ptr can answer safely.
This, we agree on. Ref_ptr can (and does) answer thoe questions.
>If you want to keep a pointer to such an object for any
>extended amount of time, you must keep a ref_ptr.
>When you pass an address into OSG, and OSG will keep
>a pointer to that block of memory, and that block of memory is a
class
>derived from Referenced, then OSG will keep a ref_ptr to that
>address.
No, that's totally wrong. The originator of an object
must be the first to encapsulate an object in ref_ptr.
You're mistaken, my friend. An application can write code that allocates
something derived from Referenced, but doesn't store it in a ref_ptr;
instead the app passes it to OSG and OSG is then the first to assign a
ref_ptr to it. The app has now relinquished control of that memory. That is
typical and common. See the example code. Look at the code for
Group::addChild to see that it keeps ref_ptrs to its children.
Passing a raw pointer to an API function that then puts it
into a ref_ptr skips a reference-count and that effectively (and
wrongly)
turns that API function into the object's last owner!
Passing a raw point intoan API function that then assigns a ref_ptr to that
object increments its ref count by one. If no one else has a ref_ptr to that
memory, then the function is correctly the object's one and only owner. No
reference count was skipped. The ref count is onw, and there's one owner.
If there is a second code module that needs to access that memory, then it,
too, should have a ref_ptr to it. In that case, the ref count is 2, and
there are two "owners"; when both go away, the memory is correctly deleted.
>From your post, I get the impression that you misunderstand how ref_ptr
works. When a ref_ptr is made to point at an object, that object's ref count
is incremented. When the ref_ptr goes away or is made to not point at an
object, the object's ref count is decremented. It it is decremented to zero,
the object deletes itself (see osg::Referenced::~Referenced() ).
> I am very much against changing the API to take a ref_ptr
> instead of an address. For the simple case where your code
allocates
> something, passes it to the API, and is done with it, you would
incur
> the unnecessary cost of going through ref_ptr's constructor and
> destructor for a pointer that has no long-term life.
> Not to mention the millions of lines of application code that
would need to be
> modified if this API change were ever implemented.
If the caller passes an object that the API only temporarily uses
(doesn't keep)
during the call, the convention in C++ is to pass it as a reference
rather than a pointer (since references cannot be deleted).
?? I'm confused. The addChild() example you mentioned will hold it
long-term, and may very well delete it if it's the last owner. It's
parameter is a pointer; this fits in with the convention you cited
perfectly.
Any passed object that the OSG API may keep after the API call,
should be encapsulated in a ref_ptr.
As I said in my previous email, an application that doesn't intend to keep a
pointer to that memory should not be forced to create a ref_ptr that will
simply be deleted after the function call, thus incurring the unnecessary
overhead of ref_ptr's constructor and destructor.
I suggested _adding_ API functions using ref_ptr.
Existing code can stay the same thanks to function overloading:
Suggestions are welcome, but, with all due respect, I encourage you to
become familiar with how the current system works before you suggest
improvements. I believe your suggestion has no benefit over the current
implementation and actually increases overhead.
Group::addNode( Node* node );
Group::addNode( ref_ptr<Node> node ); // additional variant
> Objects derived
>from Referenced are only deleted when the reference count reaches
>zero, which occurs when the last ref_ptr is deleted.Memory should
>never be deleted twice unless you are trying to take ownership, and
>your code is calling ref/unref directly. Don't do this. This is bad
>coding practice. Instead, use a ref_ptr and never call ref/unref
>directly. Please post again if this is still confusing. Paul
Martz
>Skew Matrix Software LLC http://www.skew-matrix.com 303 859 9466
That's the whole point of why I want to use ref_ptr:
it eliminates explicit error-prone "delete" calls.
Indeed. Ref_ptr was created to avoid error-prone "delete" calls (memory
leaks).
-Paul
_______________________________________________
osg-users mailing list
[email protected]
http://openscenegraph.net/mailman/listinfo/osg-users
http://www.openscenegraph.org/