TracNav menu
-
Home
- About
-
Features
- Performance
- Multi-Threading
- Clustering
- Extensibility
- Comparison
-
Getting Started
-
Download
- Releases
- Dependencies
- Daily Builds
- Source
- API Documentation
- Building
- Demos
-
Help
- Tutorial
- FAQ
- How to?
- Reference
-
Community
- Application Gallery
- Mailing lists
-
External Support
- OpenSG Forum
- OpenSG Plus
- Users
-
Development
- Developers
-
Contributing
- CodeBazaar
- ProjectIdeas
-
Future
- Documentation
- Marketing
- Building
- File IO
- CodingStandard
Miscellaneous Notes on the OpenSG 2 Design
This page just collects notes on decisions during the development of OpenSG 2, particularly the move of reference counts into the fields.
- GlobalReferencePointer
-
Problem: global objects in a program are kept alive by their ref pointers past the call to osgExit (especially if it is done explicitly). This causes crashes when the d'tors for the pointers are finally called, because the FieldContainerFactory is already destroyed (the attempt to unregister the FC crashes).
Solution: a special type of pointer has to be used for these objects. It internally keeps a list of all instances of GlobalReferencePointers and registers a PreFactoryExit-function that clears these pointers.
- Child/ParentPointerField Sync
-
Problem: There is a tight relationship between a child and the corresponding parent field, making an entry into a child field, will also cause an entry in the corresponding parent field. For objects that can only have a single parent there is another complication: the child has to be removed from the old parent. For the changed notification all three modified fields have to be recorded in the changelist, but when performing the sync to another aspect only the new parent's child field needs to be copied, the changes to the other fields will automatically replay. For parent fields this is easy to achieve as they would never have to be recorded as modified, they are always implicitly changed as well, BUT for the old parent's child field the changes would have to be ignored depending on circumstances, i.e. whether the child field was edited directly or only as part of the re-parenting of a child.
Solution: Pointer fields are simply copied and only the reference counts of the pointed to objects are adjusted (in FieldTypeName::syncWith). The downside of this approach is that filtering of changelist entries becomes very complicated, because there are now different entries (for the different involved containers) that logically are part of the same "change".
- Pointer Field Hierarchy
-
Field <--- Pointer{S|M}FieldBase ^ | +- Pointer{S|M}FieldCommon<AccessHandlerT, NamespaceI> <-+- ChildPointer{S|M}FieldBase <--- ChildPointer{S|M}Field<ObjectTypeT> | +- ParentPointer{S|M}FieldBase <--- ParentPointer{S|M}Field<ObjectTypeT> | +- UnrecordedPointer{S|M}FieldBase <--- UnrecordedPointer{S|M}Field<ObjectTypeT> | +- WeakPointer{S|M}FieldBase <--- WeakPointer{S|M}Field<ObjectTypeT>
- Pointer{S|M}FieldBase
provides read-only access (through the const part of std::vector's interface), but only gives you FieldContainerPtr independent of the real pointer type.
- Pointer{S|M}FieldCommon<AccessHandlerT, NamespaceI>
implements an interface that is mainly for internal use and handles all ref counting/child linking (by calling functions of its AccessHandlerT argument).
The biggest caveat of with this interface is that it can not handle parent fields fully correctly, as these store additional data with the pointer. However, parent fields almost never need to be modified explicitly (the aspect sync being the one exception, but that is handled internally), so this should not be an issue normally. Derived classes can call the functions provided here instead of implementing them themselves to reduce the amount of code instantiated for each pointer type.
- {Child|Parent|Unrecorded|Weak}Pointer{S|M}FieldBase
are meant as the classes through which the Pointer{S|M}FieldCommon are actually used, if that is needed. This provides a somewhat generic interface, that does not require knowledge of what pointers are exactly stored in the field, but it does require knowledge of the "class" (data, child pointer, parent pointer, unrecorded pointer, weak pointer) and "cardinality" (single, multi) of the field
- {Child|Parent|Unrecorded|Weak}Pointer{S|M}Field<ObjectTypeT>
provide the full std::vector interface and are what is used everywhere inside the library and user code. These fields return properly typed pointers instead of the FieldContainerPtr returned by all the base classes.
