Drake
DependencyTracker Class Reference

Manages value interdependencies for a particular value or set of values in a Context. More...

#include <drake/systems/framework/dependency_tracker.h>

## Public Types

using PointerMap = std::unordered_map< const DependencyTracker *, const DependencyTracker * >
(Internal use only) More...

## Public Member Functions

const std::string & description () const
Returns the human-readable description for this tracker. More...

std::string GetPathDescription () const
Returns the description, preceded by the full pathname of the subsystem associated with the owning subcontext. More...

DependencyTicket ticket () const
Returns the DependencyTicket for this DependencyTracker in its containing DependencyGraph. More...

void set_cache_entry_value (CacheEntryValue *cache_value)
(Internal use only) Sets the cache entry value to be marked out-of-date when this tracker's prerequisites change. More...

const CacheEntryValuecache_entry_value () const
(Internal use only) Returns a pointer to the CacheEntryValue if this tracker is a cache entry tracker, otherwise nullptr. More...

void NoteValueChange (int64_t change_event) const
Notifies this DependencyTracker that its managed value was directly modified or made available for mutable access. More...

Does not allow copy, move, or assignment
DependencyTracker (const DependencyTracker &)=delete

DependencyTrackeroperator= (const DependencyTracker &)=delete

DependencyTracker (DependencyTracker &&)=delete

DependencyTrackeroperator= (DependencyTracker &&)=delete

Prerequisites and subscribers

These methods deal with dependencies associated with this tracker.

void SubscribeToPrerequisite (DependencyTracker *prerequisite)
Subscribes this tracker to an upstream prerequisite's tracker. More...

void UnsubscribeFromPrerequisite (DependencyTracker *prerequisite)
Unsubscribes this tracker from an upstream prerequisite tracker to which we previously subscribed. More...

Adds a downstream subscriber to this DependencyTracker, which will keep a pointer to the subscribing tracker. More...

void RemoveDownstreamSubscriber (const DependencyTracker &subscriber)
Removes a downstream subscriber from this DependencyTracker. More...

bool HasPrerequisite (const DependencyTracker &prerequisite) const
Returns true if this tracker has already subscribed to prerequisite. More...

bool HasSubscriber (const DependencyTracker &subscriber) const
Returns true if subscriber is one of this tracker's subscribers. More...

int num_prerequisites () const
Returns the total number of "depends-on" edges emanating from this tracker, pointing to its upstream prerequisites. More...

const std::vector< const DependencyTracker * > & prerequisites () const
Returns a reference to the prerequisite trackers. More...

int num_subscribers () const
Returns the total number of "is-prerequisite-of" edges emanating from this tracker, pointing to its downstream subscribers. More...

const std::vector< const DependencyTracker * > & subscribers () const
Returns a reference to the subscribing trackers. More...

Runtime statistics

These methods track runtime operations and are useful for debugging and for performance analysis.

How many times did we receive a repeat notification for the same change event that we ignored? More...

What is the total number of notifications sent to downstream subscribers by this trackers? More...

int64_t num_value_change_events () const
How many times was this tracker notified of a change event for a direct change to a value it tracks? More...

int64_t num_prerequisite_change_events () const
How many times was this tracker notified of a change to one of its value's prerequisites? More...

Testing/debugging utilities

Methods used in test cases or for debugging.

void ThrowIfBadDependencyTracker (const internal::ContextMessageInterface *owning_subcontext=nullptr, const CacheEntryValue *cache_value=nullptr) const
Throws an std::logic_error if there is something clearly wrong with this DependencyTracker object. More...

## Friends

class DependencyGraph

## Detailed Description

Manages value interdependencies for a particular value or set of values in a Context.

A DependencyTracker ("tracker" for short) provides notifications of changes to the managed value to downstream subscribers, and may invalidate an associated cache entry. The "managed value" can be a source like time or state, or a cached computation. A particular tracker is selected using a DependencyTicket ("ticket") which provides very fast access to the tracker. The ticket is used by both the System and Context as a way to identify dependencies, while trackers exist only in the Context.

Each DependencyTracker manages dependencies for a value, or group of related values, upon which some downstream computations may depend, and maintains lists of downstream dependents (subscribers) and upstream prerequisites. An optional CacheEntryValue may be registered with a tracker in which case the tracker will mark the cache value out of date when one of its prerequisites has changed.

A single DependencyTracker can represent interdependencies within its subcontext, and to and from other subcontexts within the same containing Context tree. Trackers are always owned by a DependencyGraph that is part of a particular subcontext, and should always be created through methods of DependencyGraph; don't construct them directly yourself.

DependencyTracker objects within a Context are nodes in a directed acylic graph formed by "is-prerequisite-of" edges leading from source values (like time, state, parameters, and input ports) to dependent cached computations and output ports. A DependencyTracker maintains lists of both its downstream subscribers and its upstream prerequisites. The entries in both lists are pointers to other DependencyTrackers. That requires special handling when cloning a Context, since the internal pointers to the DependencyTracker objects in the source must be replaced by their corresponding pointers in the copy.

DependencyTrackers may simply group upstream values, without representing a new value or computation. For example, the three continuous state subgroups q, v, and z are each associated with their own DependencyTracker. There is also a tracker that monitors changes to any variable within the entire collection of continuous variables xc≜{q,v,z}; that tracker subscribes to the three individual trackers. Similarly, individual discrete variable groups dᵢ collectively determine the discrete state xd≜{dᵢ}, individual abstract state variables aᵢ determine the abstract state xa≜{aᵢ}, and the full state is x≜{xc,xd,xa}. Here is a graph showing time and state trackers and some hypothetical cache entry trackers.

                   (q)--------➙(position kinematics)
➘
(v)--➙(xc)---     (time)----➙(xc_dot)
(z)--➚       ╲              ➚
➘            ╱
(d₀)--➙(xd)---➙(x)----------
(d₁)--➚        ➚
╱
(a₀)--➙(xa)---
(a₁)--➚


The parenthesized nodes are DependencyTrackers for the indicated values, and a directed edge (a)->(b) can be read as "a is-prerequisite-of b" or "a determines b". The graph also maintains reverse-direction edges (not shown). A reversed edge (a)<-(b) could be read as "b subscribes-to a" or "b depends-on a".)

These grouped trackers simplify dependency specification for quantities that depend on many sources, which is very common. For example, they allow a user to express a dependence on "all the inputs" without actually having to know how many inputs there are, which might change over time. Grouped trackers also serve to reduce the total number of edges in the dependency graph, providing faster invalidation. For example, if there are 10 computations dependent on q, v, and z (which frequently change together) we would have 30 edges. Introducing (xc) reduces that to 13 edges.

Downstream computations may subscribe to any of the individual or grouped nodes.

## ◆ PointerMap

 using PointerMap = std::unordered_map

(Internal use only)

## ◆ DependencyTracker() [1/2]

 DependencyTracker ( const DependencyTracker & )
delete

## ◆ DependencyTracker() [2/2]

 DependencyTracker ( DependencyTracker && )
delete

## Member Function Documentation

 void AddDownstreamSubscriber ( const DependencyTracker & subscriber )

Adds a downstream subscriber to this DependencyTracker, which will keep a pointer to the subscribing tracker.

The subscriber will be notified whenever this DependencyTracker is notified of a value or prerequisite change.

Precondition
The subscriber has already recorded its dependency on this tracker in its prerequisite list.

## ◆ cache_entry_value()

 const CacheEntryValue* cache_entry_value ( ) const
inline

(Internal use only) Returns a pointer to the CacheEntryValue if this tracker is a cache entry tracker, otherwise nullptr.

## ◆ description()

 const std::string& description ( ) const
inline

Returns the human-readable description for this tracker.

## ◆ GetPathDescription()

 std::string GetPathDescription ( ) const

Returns the description, preceded by the full pathname of the subsystem associated with the owning subcontext.

## ◆ HasPrerequisite()

 bool HasPrerequisite ( const DependencyTracker & prerequisite ) const

Returns true if this tracker has already subscribed to prerequisite.

This is slow and should not be used in performance-sensitive code.

## ◆ HasSubscriber()

 bool HasSubscriber ( const DependencyTracker & subscriber ) const

Returns true if subscriber is one of this tracker's subscribers.

This is slow and should not be used in performance-sensitive code.

## ◆ NoteValueChange()

 void NoteValueChange ( int64_t change_event ) const

Notifies this DependencyTracker that its managed value was directly modified or made available for mutable access.

That is, this is the initiating event of a value modification. All of our downstream subscribers are notified but the associated cache entry (if any) is not invalidated (see below for why). A unique, positive change_event should have been obtained from the owning Context and supplied here.

Why don't we invalidate the cache entry? Recall that this method is for initiating a change event, meaning that the quantity that this tracker tracks is initiating an invalidation sweep, as opposed to just reacting to prerequisite changes. Normally cache entries become invalid because their prerequisites change; they are not usually the first step in an invalidation sweep. So it is unusual for NoteValueChange() to be called on a cache entry's dependency tracker. But if it is called, that is likely to mean the cache entry was just given a new value, and is therefore valid; invalidating it now would be an error.

inline

How many times did we receive a repeat notification for the same change event that we ignored?

inline

inline

What is the total number of notifications sent to downstream subscribers by this trackers?

## ◆ num_prerequisite_change_events()

 int64_t num_prerequisite_change_events ( ) const
inline

How many times was this tracker notified of a change to one of its value's prerequisites?

## ◆ num_prerequisites()

 int num_prerequisites ( ) const
inline

Returns the total number of "depends-on" edges emanating from this tracker, pointing to its upstream prerequisites.

## ◆ num_subscribers()

 int num_subscribers ( ) const
inline

Returns the total number of "is-prerequisite-of" edges emanating from this tracker, pointing to its downstream subscribers.

## ◆ num_value_change_events()

 int64_t num_value_change_events ( ) const
inline

How many times was this tracker notified of a change event for a direct change to a value it tracks?

## ◆ operator=() [1/2]

 DependencyTracker& operator= ( DependencyTracker && )
delete

## ◆ operator=() [2/2]

 DependencyTracker& operator= ( const DependencyTracker & )
delete

## ◆ prerequisites()

 const std::vector& prerequisites ( ) const
inline

Returns a reference to the prerequisite trackers.

## ◆ RemoveDownstreamSubscriber()

 void RemoveDownstreamSubscriber ( const DependencyTracker & subscriber )

Removes a downstream subscriber from this DependencyTracker.

Precondition
The subscriber has already removed the dependency on this tracker from its prerequisite list.

## ◆ set_cache_entry_value()

 void set_cache_entry_value ( CacheEntryValue * cache_value )
inline

(Internal use only) Sets the cache entry value to be marked out-of-date when this tracker's prerequisites change.

Precondition
The supplied cache entry value is non-null.
No cache entry value has previously been assigned.

## ◆ subscribers()

 const std::vector& subscribers ( ) const
inline

Returns a reference to the subscribing trackers.

## ◆ SubscribeToPrerequisite()

 void SubscribeToPrerequisite ( DependencyTracker * prerequisite )

Subscribes this tracker to an upstream prerequisite's tracker.

The upstream tracker will keep a const pointer back to this tracker in its subscriber list, and this tracker will keep a pointer to the prerequisite tracker in its prerequisites list.

 void ThrowIfBadDependencyTracker ( const internal::ContextMessageInterface * owning_subcontext = nullptr, const CacheEntryValue * cache_value = nullptr ) const

Throws an std::logic_error if there is something clearly wrong with this DependencyTracker object.

If the owning subcontext is known, provide a pointer to it here and we'll check that this tracker agrees. If you know which cache entry is supposed to be associated with this tracker, supply a pointer to that and we'll check it (trackers that are not associated with a real cache entry are still associated with the CacheEntryValue::dummy()). In addition we check for other internal inconsistencies.

Exceptions
 std::logic_error for anything that goes wrong, with an appropriate explanatory message.

## ◆ ticket()

 DependencyTicket ticket ( ) const
inline

Returns the DependencyTicket for this DependencyTracker in its containing DependencyGraph.

The ticket is unique within the containing subcontext.

## ◆ UnsubscribeFromPrerequisite()

 void UnsubscribeFromPrerequisite ( DependencyTracker * prerequisite )

Unsubscribes this tracker from an upstream prerequisite tracker to which we previously subscribed.

Both the prerequisite list in this tracker and the subscriber list in prerequisite are modified.

Precondition
The supplied pointer must not be null.
This tracker must already be subscribed to the given prerequisite.

## ◆ DependencyGraph

 friend class DependencyGraph
friend

The documentation for this class was generated from the following files: