The evaluation of actions is performed only when explicitly requested. AutoCAD explicitly requests evaluation of the top level network of the database at the beginning and at the end of each command, when the document lock mode changes, and during dragging on every drag sample. The evaluation can also be explicitly requested by the client code, but usually this is not necessary.
Although, sub networks or individual actions can be explicitly evaluated by calling their AcDbAssocAction::evaluate() method, it is preferable to always evaluate the top level network of the database by calling AcDbAssocManager::evaluateTopLevelNetwork(). Evaluation of the whole top level network guarantees that all actions that need to be evaluated, are evaluated. There is no performance penalty by always evaluating the whole top level network of the database even if it contains many sub networks and many actions.
There is a separation between change notification and network evaluation because of these changes.
When an object that has dependencies attached to it is modified, the following sequence of notifications occurs:
- Each dependency attached to the object checks if the object change is relevant for that dependency. If not, nothing happens. If yes, the dependency changes its AcDbAssocStatus to kChangedDirectlyAssocStatus.
- The dependency notifies the action owning the dependency. The action changes its own AcDbAssocStatus to kChangedDirectlyAssocStatus.
- The action notifies the owning network. The network changes its own AcDbAssocStatus to kChangedDirectlyAssocStatus. This continues up to the top level network.
- No automatic network evaluation occurs.
When a network evaluation is requested by calling AcDbAssocAction::evaluate(), the following sequence of events occurs:
- At the beginning, a transitive closure of all actions that need to be evaluated is obtained, and the AcDbAssocStatus of all such additionally collected dependencies and actions is changed to kChangedTransitivelyAssocStatus or kChangedNoDifferenceAssocStatus.
- The transitive closure is obtained by calling AcDbAssocAction::getDependentActionsToEvaluate() method on all actions that are already marked for evaluation, until no more actions can be collected. The default implementation of AcDbAssocAction::getDependentActionsToEvaluate() is based on the action dependencies, but the client code may provide its own implementation by overriding the AcDbAssocActionBody::getDependentActionsToEvaluateOverride() method.
- The AcDbAssocAction::evaluationPriority() is called on all actions that have been collected for evaluation.
- The action with the highest evaluation priority is evaluated by calling its AcDbAssocAction::evaluate() method.
- This invokes the custom evaluation algorithm of the action implemented by the action's AcDbAssocActionBody::evaluateOverride() method. At the end, this custom algorithm needs to set the action status to kIsUpToDateAssocStatus or kFailedToEvaluateAssocStatus, depending on whether the action considered its execution successful or not. It also needs to call evaluateDependencies() to evaluate the owned dependencies, which updates their caches and sets their status to kIsUpToDateAssocStatus.
- Evaluating an action may unblock the evaluation of other actions. The next action with the highest evaluation priority is evaluated.
- This process continues until all actions have been evaluated.
- If no action can be evaluated, an action with the highest evaluation priority is chosen and forced to evaluate even if its evaluation priority indicates that it cannot be evaluated. This forced evaluation of an action may unblock other actions from being evaluated, for example, by breaking a deadlock.