Hi,

Dirk Reiners wrote:
>       Hi Allen,
> 
> Allen Bierbaum wrote:
>> Could you or Carsten give us a run down of the changes you are going 
>> after?  I would really like to see some details about how this is going 
>> to end up so we can start planning and so some of the rest of us could 
>> start giving some feedback on the ideas.
> 
> We've been throwing ideas around between us, and we're trying to come up 
> with something workable but there are some areas that we will need 
> feedback. RefCounting and clusters is not a trivial thing to do...
> Coming up soon...

maybe it is best if I start with a description of how things are done on 
the trunk at the moment (at least the way I read the code ;) ):
- pointer fields store C ptrs
- the interface in the <FCName>Base classes does not grant access to 
pointer fields, but they can be modified either through a set of 
functions or through the GetFieldHandle/EditFieldHandle classes returned 
by the generic interface. For example, let's take a look at Viewport, 
which has (among others) an SFBackgroundPtr _sfBackground and 
MFForegroundPtr _mfForegrounds accessible through:

const SFBackgroundPtr    *getSFBackground(void) const;
       BackgroundPtrConst  getBackground  (void) const;
void                      setBackground  (BackgroundPtrConstArg value);

const MFForegroundPtr   *getMFForegrounds(void) const;
       ForegroundPtrConst getForegrounds  (const UInt32 index) const;
const MFForegroundPtr   &getForegrounds  (void) const;

void addForeground(ForegroundPtrConstArg value           );
void assignForegrounds(const MFForegroundPtr   &value    );
void insertIntoForegrounds(UInt32                uiIndex,
                            ForegroundPtrConstArg value   );
void replaceInForegrounds(UInt32                uiIndex,
                           ForegroundPtrConstArg value    );
void replaceInForegrounds(ForegroundPtrConstArg pOldElem,
                           ForegroundPtrConstArg pNewElem );
void removeFromForegrounds(UInt32                uiIndex );
void removeFromForegrounds(ForegroundPtrConstArg value   );
void clearForegrounds     (void                          );

and the generic interface:

EditFieldHandlePtr editField(      UInt32 fieldId  );
EditFieldHandlePtr editField(const Char8 *fieldName);
GetFieldHandlePtr  getField (      UInt32 fieldId  ) const;
GetFieldHandlePtr  getField (const Char8 *fieldName) const;

The reference count is maintained by explicit calls to addRef/subRef 
inside these generated functions and since there is no "legal" way to 
bypass these (well, there is const_cast ...) it is much harder to break 
things than in OpenSG 1.

Now, instead of managing the ref count in the access functions we could 
just store smart pointers that do the ref counting in the c'tors and 
assignment operators. One problem that we have to deal with then are 
circles in the pointed to chains, which for OpenSG are introduced only 
(?) through parent pointers, e.g. in NodeCore. These pointers would 
become weak pointers (which modify a separate weak ref count in each 
field container [1]).
Except for the introduction of weak pointers (which in a sense we have 
right now as well, as the parent pointers do not increment the ref count 
of the object they point to) this is similar enough to what we do right 
now that at least on one machine it should work. The cluster adds 
another difficulty on top of that: On the remote side not all pointers 
are replicated, because some are not held inside field containers, but 
by the application instead. This can cause an object to be deleted on 
the remote side although it is kept alive locally (by a pointer held by 
the application). If that object later is again pointed to by a field 
container the remote side would have to recreate the pointed to object's 
contents virtually out of thin air [2]. Right now we create entries in 
the changelist for every increment/decrement of the reference count and 
simply replay that record on the remote side. The crucial observation 
here is that when the RemoteAspect fills a pointer field with values 
(i.e. pointers) it does so without affecting the pointed to objects ref 
count, but instead relies on the replay of changelist entries. Storing 
ref pointers in the fields makes it impossible [3] to bypass the ref 
counting and therefore a simple replay of changelist entries would lead 
to wrong values for the counters.
In order to solve this, the ref pointers stored in fields will be of a 
type (InternalRefPtr<ContainerTypeT>) distinct from those used by 
applications (RefPtr<ContainerTypeT>). InternalRefPtrs do not generate 
add/subRef changelist entries but affect the normal (per aspect) 
reference count stored in FieldContainer. RefPtrs on the other hand 
generate changelist entries, but they modify a different counter 
(_iExternalRefCount) that is kept in AspectStore. These changelist 
entries are ignored during a local apply, however the RemoteAspect does 
replay these on the remote side. Objects are only destroyed of all three 
reference counts are less or equal zero. The solution for circular 
references in [1] would have to be modified to read: Pointer fields are 
emptied as soon as _iExternalRefCount <= 0 && _iRefCount <= 0.

If you have questions, concerns or scenarios where the above scheme will 
break, please let us know. As Dirk already said, getting these things 
right is tricky and reasoning about them is not trivial, so we are more 
than happy to revise the above plan if it turns out to have flaws.

        Thanks, 
                Carsten

[1] The reason for the separate weak ref count is to have a way to tell 
if a weak ptr still points to a "live" object. A pointed to field 
container would not be deleted until both weak and regular ref count 
become less or equal zero. In order to prevent the circular references 
problem, (pointer) fields would be emptied as soon as the regular ref 
count becomes less or equal zero.

[2] Locally this works because there is always the source aspect 
available to copy/share data from/with. But since only changes to an 
objects contents are transmitted the remote side would not receive a new 
copy of data. Introducing a back-channel on which the RemoteAspect can 
request a retransmit of the data unfortunately defeats the idea of being 
able to run the cluster with broadcasts.

[3] Well, not quite impossible, but the ref pointers would need to have 
an interface that allows to modify the pointer they store internally 
without affecting the pointed to objects ref count. However, this 
somewhat defeats the whole idea of ref pointers.


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Opensg-core mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-core

Reply via email to