Hi Gerrit, all,
Gerrit Voß wrote:
>> relatively, the problem is that the only consistent thing they export is
>> the blob (sp_counted_base), not the atomic operations we need, so we
>> might take some inspiration from there but I guess we have to do the
>> two required functions (atomicInc, atomicExAndAdd) by ourselves. But
>> we can fallback to boost where we can.
>>
>
> which we do now, could you try and let us know if the change to atomic
> counting makes any difference for your app ?
unfortunately this broke one of the unit tests (I'm about to have them
back in working order),
Source/System/NodeCores/Groups/Light/OSGLightReferenceCountTest.cpp.
The problem is that the modification of the ref counts moved with
respect to the resolveLinks() call (which can affect the the ref count
of the current container through weak pointers from elsewhere in the tree).
The tree for the test looks like this:
// np0[gp0] <------------+
// +----------+ |
// np1[gp1] np2[gp2] | beacon
// | |
// np3[lp0]--------------+
and there is only one rec pointer to np0 that then is set to NULL to get
rid of the whole tree.
Before, np0 had a ref count of 1 when np3 performed its resolveLinks()
and subsequently called subWeakReference() on np0. Therefore the if
inside subWeakReference never applied and the container was not deleted
from subWeakReference, but instead later when control returned to the
subReferenceRecorded on np0.
First I thought we could fix this by just getting rid of the
(superfluous anyways) resolveLinks() inside subWeakReference(). But,
there is still the problem of the np0 d'tor running early (while
children field of np0 is in the process of being emptied).
Thinking about this some more Dirk and I found three problematic scenarios:
1) the above situation with a beacon pointing "back" to an object that
already has a sub[Weak]Reference() running,
2) an object that only has a weak pointer to it (e.g. it is held in a
cache).
3) two threads one giving up a reference to an object the other one
giving up a weak reference (this case currently still has a race I think).
We noticed that all three problems can be solved if weak references do
not keep the object "alive". For 1) the d'tor will not run early when
the weak reference from lp0 goes away, for 2) the object must have been
cleaned up when the last strong reference went away and for 3) we only
need to ensure that the threads atomically modify the ref counts and
base their actions on the previous value.
The idea to solve this is to have the weak pointers point at the
AspectStore (and use its ref count to count weak refs as well). Then we
can destroy the FieldContainer objects when the last strong reference
goes away, but the weak pointer can still detect this (the aspect store
will have a NULL pointer for the current aspect). A side-effect of this
is that all WeakPtr will in fact be MTWeakPtr, but there should be few
of them compared to the regular pointers, so the penalty for going to
the AspectStore should overall not be too big.
Also, I think this makes the implementation pretty close to what boost
does with their shared_ptr/weak_ptr where they have the on-the-side blob
holding the ref count(s) and real pointer to the object.
Comments? Cases we overlooked?
Cheers,
Carsten
------------------------------------------------------------------------------
_______________________________________________
Opensg-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-users