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