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

Reply via email to