Carsten: I appreciate the detailed description. I think I have to read it a few more times to fully grasp the internal details.
What I think would be useful would be to describe the the user-level API would look like. For example, will a user application only use RefPtr's? Will these handle all the internal details automatically? How will user apps handle aspects or will this be hidden? When the user needs a true cptr, how will they get them. I guess what I am saying is that I am asking a much simpler question of what will everything look like to users. I am just trusting that you and Dirk will be able to get everything working correctly internally. :) -Allen Carsten Neumann wrote: > 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 > ------------------------------------------------------------------------- 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
