Circular References

Circular references are not prohibited by Scenome's directed acyclic graph or dependency graph but creating circular references, either by accident, or by direct action, is not best practice. Circular references may cause infinite traversal in Scenome or in your runtime because the application will traverse the pointer list in order and return to the starting point again and again and again...

Circular references occur when two or more nodes are linked by a collection of pointers that reference each other in a cyclical manner. To prevent this, the dependency graph should follow the same rules as the directed acyclic graph and provide guaranteed termination for every pointer in the graph. Generally speaking, you can only create undesirable circular references with link nodes.

Example 1, Dependencies

This example examines the concept of literal, pointer-based dependencies. A literal pointer-based dependency occurs when a node points at another node by storing a pointer to that node. This pointer is implemented in the node's class itself. For example, the material node data structure, implemented in MATERIAL.CPP, contains code that stores a pointer to a texture node. [NOTE: TEXTURE.CPP, which implements texture node, DOES NOT contain any code that allows it to point at a material node. This is important to consider if you implement your own nodes.]

Figure 1.1. Dependencies. A material node and texture node with a relationship specified by the material node. The material node is dependent on the texture node. If you change the texture node, or delete it, the material node is affected. However, if you delete the material node, or change the material node, the texture node is not affected at all.

Figure 1.2. Dependencies. A material node and texture node with a relationship specified by a link node. When this structure is traversed, starting with the material node, the pointer structure terminates at TextureNode. MaterialNode is dependent upon LinkNode because it stores a pointer to LinkNode. LinkNode is dependent upon TextureNode because it stores a pointer to TextureNode. TextureNode is not dependent upon LinkNode or MaterialNode because TextureNode does not store a pointer to either node. [TextureNode cannot store such a pointer.]

Example 2, References

This example examines the concept of references. References occur when a node is pointed-at by another node. A dependency occurs only when one node points directly at another node. A reference occurs when a node is pointed-at by another node. You can query any node to find its dependencies but finding references for a node involves searching every node in the database. Circularity is not of great concern with respect to references. [If you traverse multiple levels of a reference graph you will almost always encounter circularities at some point.]

Figure 1.3. References. A material node and texture node with a relationship specified by a link node. If you start with TextureNode and derive its references by testing every node in the database, you find LinkNode. If you test LinkNode and derive its references, you find MaterialNode. Deriving references is like asking "What nodes store a pointer to me?"

Example 3, Circular References

This example examines a circular reference. Generally speaking, you cannot easily create a circular reference between any nodes without using a link node. For example, you cannot create a circular reference between a material and texture because a texture node cannot store a pointer to a material. Link nodes are different; a link node can store a pointer to any node in the database, including its parent.

Figure 1.4. Circular References. Three link nodes that reference each other in a circular pointer list. LinkNode1 points at LinkNode2. Continuing, you find that LinkNode2 points at LinkNode3, and that LinkNode3 points at LinkNode1. Now we're back where we started and can continue traversing infinitely. This is a great example of a pointer structure that fails to terminate properly.

The correct implementation

Example 4, Circular References

This example examines a circular reference that is a little trickier.

Figure 1.5. Circular References. This node link references its own parent. When Scenome traverses the root node child list, it eventually finds LinkNode1. LinkNode1 sends traversal back to root node. When Scenome traverses the root node child list, it eventually finds LinkNode1... you get the idea.

Also incorrect:

This is perfectly legal:

Example 5, Circular References

This example examines another case of circular referencing. This time the circular reference is created in with two separate databases

Figure 1.6. Circular References Between Files. These files reference each other in a circular manner. Like other forms of circular reference, this is not illegal, but it is not best practice.

Working With Scenome

Generally speaking it is tough to create circular references unless you do so directly. NEVER POINT A NODELINK AT THE ROOT NODE OR ANY OF ITS PARENT NODES! That said, Scenome does not prohibit such relationships and it is up to you to avoid creating them.