(Advanced) This is the representation in the Context for the value of one of a System's CacheEntry objects.
Most users will not use this class directly – System and CacheEntry provide the most common APIs, and Context provides additional useful methods.
A CacheEntryValue consists of a single type-erased value, a serial number, an out_of_date
flag, and a DependencyTracker ticket. Details:
out_of_date
flag here, and mark all downstream dependents out of date also. The tracker lives in the same subcontext that owns the Cache that owns this CacheEntryValue.We sometimes use the terms "invalid" and "invalidate" as synonyms for "out of date" and "mark out of date".
For debugging purposes, caching may be disabled for an entire Context or for particular cache entry values. This is independent of the out_of_date
flag described above, which is still expected to be operational when caching is disabled. However, when caching is disabled the Eval() methods will recompute the contained value even if it is not marked out of date. That should have no effect other than to slow computation; if results change, something is wrong. There could be a problem with the specification of dependencies, a bug in user code such as improper retention of a stale reference, or a bug in the caching system.
#include <drake/systems/framework/cache.h>
Public Member Functions | |
~CacheEntryValue ()=default | |
Destructs the cache value, but does not issue any notifications to downstream dependents. More... | |
void | SetInitialValue (std::unique_ptr< AbstractValue > init_value) |
Defines the concrete value type by providing an initial AbstractValue object containing an object of the appropriate concrete type. More... | |
Does not allow move or assignment; copy constructor is private. | |
CacheEntryValue (CacheEntryValue &&)=delete | |
void | operator= (const CacheEntryValue &)=delete |
void | operator= (CacheEntryValue &&)=delete |
Safe methods for value access and modification | |
These are the recommended methods for accessing and modifying the cache entry value. They unconditionally check all the relevant preconditions to catch usage errors. In particular, access is prevented when the value is out of date, and modification is permitted only when (a) the value is already out of date (typically because a prerequisite changed), or (b) caching is disabled for this entry. For performance-sensitive code, you may need to use the parallel set of methods below that check preconditions only in Debug builds, but be sure you are gaining significant performance before giving up on Release-build validation. | |
const AbstractValue & | GetAbstractValueOrThrow () const |
Returns a const reference to the contained abstract value, which must not be out of date with respect to any of its prerequisites. More... | |
template<typename V > | |
const V & | GetValueOrThrow () const |
Returns a const reference to the contained value of known type V. More... | |
template<typename V > | |
void | SetValueOrThrow (const V &new_value) |
Assigns a new value to a cache entry and marks it up to date. More... | |
AbstractValue & | GetMutableAbstractValueOrThrow () |
(Advanced) Returns a mutable reference to the contained value after incrementing the serial number. More... | |
template<typename V > | |
V & | GetMutableValueOrThrow () |
(Advanced) Convenience method that returns a mutable reference to the contained value downcast to its known concrete type. More... | |
const AbstractValue & | PeekAbstractValueOrThrow () const |
(Advanced) Returns a reference to the contained value without checking whether the value is out of date. More... | |
template<typename V > | |
const V & | PeekValueOrThrow () const |
(Advanced) Convenience method that provides access to the contained value downcast to its known concrete type, without checking whether the value is out of date. More... | |
Fast-but-dangerous methods for highest performance | |
These methods check for errors only in Debug builds, but plunge blindly onward in Release builds so that they will execute as fast as possible. You should use them only in places where performance requirements preclude Release-build checks. The best way to determine that is to time the code using the always-checked methods vs. these ones. If that's not practical, use these only when the containing code is in a very high-rate loop, and is a substantial fraction of the total code being executed there. | |
const AbstractValue & | get_abstract_value () const |
Returns a const reference to the contained abstract value, which must not be out of date with respect to any of its prerequisites. More... | |
template<typename V > | |
const V & | get_value () const |
Returns a const reference to the contained value of known type V. More... | |
template<typename V > | |
void | set_value (const V &new_value) |
Assigns a new value to a cache entry and marks it up to date. More... | |
void | swap_value (std::unique_ptr< AbstractValue > *other_value) |
(Advanced) Swaps ownership of the stored value object with the given one. More... | |
Dependency management | |
Methods here deal with management of the | |
bool | is_out_of_date () const |
Returns true if the current value is out of date with respect to any of its prerequisites. More... | |
bool | needs_recomputation () const |
Returns true if either (a) the value is out of date, or (b) caching is disabled for this entry. More... | |
void | mark_up_to_date () |
(Advanced) Marks the cache entry value as up to date with respect to its prerequisites, with no other effects. More... | |
void | mark_out_of_date () |
(Advanced) Marks the cache entry value as out-of-date with respect to its prerequisites, with no other effects. More... | |
int64_t | serial_number () const |
Returns the serial number of the contained value. More... | |
Bookkeeping methods | |
Miscellaneous methods of limited use to most users. | |
const std::string & | description () const |
Returns the human-readable description for this CacheEntryValue. More... | |
std::string | GetPathDescription () const |
Returns the description, preceded by the full pathname of the subsystem associated with the owning subcontext. More... | |
bool | has_value () const |
Returns true if this CacheEntryValue currently contains a value object at all, regardless of whether it is up to date. More... | |
CacheIndex | cache_index () const |
Returns the CacheIndex used to locate this CacheEntryValue within its containing subcontext. More... | |
DependencyTicket | ticket () const |
Returns the DependencyTicket used to locate the DependencyTracker that manages dependencies for this CacheEntryValue. More... | |
Testing/debugging utilities | |
These are used for disabling and re-enabling caching to determine correctness and effectiveness of caching. Usually all cache entries are disabled or enabled together using higher-level methods that invoke these ones, but you can disable just a single entry if necessary. | |
void | ThrowIfBadCacheEntryValue (const internal::ContextMessageInterface *owning_subcontext=nullptr) const |
Throws an std::exception if there is something clearly wrong with this CacheEntryValue object. More... | |
void | disable_caching () |
(Advanced) Disables caching for just this cache entry value. More... | |
void | enable_caching () |
(Advanced) Enables caching for this cache entry value if it was previously disabled. More... | |
bool | is_cache_entry_disabled () const |
(Advanced) Returns true if caching is disabled for this cache entry. More... | |
Friends | |
class | Cache |
class | copyable_unique_ptr< CacheEntryValue > |
|
delete |
|
default |
Destructs the cache value, but does not issue any notifications to downstream dependents.
CacheIndex cache_index | ( | ) | const |
Returns the CacheIndex used to locate this CacheEntryValue within its containing subcontext.
const std::string& description | ( | ) | const |
Returns the human-readable description for this CacheEntryValue.
void disable_caching | ( | ) |
(Advanced) Disables caching for just this cache entry value.
When disabled, the corresponding entry's Eval() method will unconditionally invoke Calc() to recompute the value, regardless of the setting of the out_of_date
flag. The disabled
flag is independent of the out_of_date
flag, which will continue to be managed even if caching is disabled. It is also independent of whether the cache is frozen, although in that case any cache access will fail since recomputation is not permitted in a frozen cache. Once unfrozen, caching will remain disabled unless enable_caching() is called.
void enable_caching | ( | ) |
(Advanced) Enables caching for this cache entry value if it was previously disabled.
When enabled (the default condition) the corresponding entry's Eval() method will check the out_of_date
flag and invoke Calc() only if the entry is marked out of date. It is also independent of whether the cache is frozen; in that case caching will be enabled once the cache is unfrozen.
const AbstractValue& get_abstract_value | ( | ) | const |
Returns a const reference to the contained abstract value, which must not be out of date with respect to any of its prerequisites.
It is an error to call this if there is no stored value, or it is out of date. Because this is used in performance-critical contexts, these requirements will be checked only in Debug builds. If you are not in a performance-critical situation (and you probably are not!), use GetAbstractValueOrThrow() instead.
const V& get_value | ( | ) | const |
Returns a const reference to the contained value of known type V.
It is an error to call this if there is no stored value, or the value is out of date, or the value doesn't actually have type V. Because this is expected to be used in performance-critical, inner-loop circumstances, these requirements will be checked only in Debug builds. If you are not in a performance-critical situation (and you probably are not!), use GetValueOrThrow<V>
() instead.
V | The known actual value type. |
const AbstractValue& GetAbstractValueOrThrow | ( | ) | const |
Returns a const reference to the contained abstract value, which must not be out of date with respect to any of its prerequisites.
It is an error to call this if there is no stored value object, or if the value is out of date.
std::exception | if there is no value or it is out of date. |
AbstractValue& GetMutableAbstractValueOrThrow | ( | ) |
(Advanced) Returns a mutable reference to the contained value after incrementing the serial number.
This is for the purpose of performing an update or extended computation in place. If possible, use the safer and more straightforward method SetValueOrThrow() rather than this method. Mutable access is only permitted if the value is already marked out of date (meaning that all downstream dependents have already been notified). It is an error to call this if there is no stored value, or it is already up to date. Since this is intended for relatively expensive computations, these preconditions are checked even in Release builds. If you have a small, fast computation to perform, use set_value() instead. If your computation completes successfully, you must mark the entry up to date yourself using mark_up_to_date() if you want anyone to be able to use the new value.
std::exception | if there is no value, or if the value is already up to date. |
std::exception | if the cache is frozen. |
V& GetMutableValueOrThrow | ( | ) |
(Advanced) Convenience method that returns a mutable reference to the contained value downcast to its known concrete type.
Throws an exception if the contained value does not have the indicated concrete type. Note that you must call mark_up_to_date() after modifying the value through the returned reference. See GetMutableAbstractValueOrThrow() above for more information.
std::exception | if there is no value, or if the value is already up to date, of it doesn't actually have type V. |
std::exception | if the cache is frozen. |
V | The known actual value type. |
std::string GetPathDescription | ( | ) | const |
Returns the description, preceded by the full pathname of the subsystem associated with the owning subcontext.
const V& GetValueOrThrow | ( | ) | const |
Returns a const reference to the contained value of known type V.
It is an error to call this if there is no stored value, or the value is out of date, or the value doesn't actually have type V.
std::exception | if there is no stored value, or if it is out of date, or it doesn't actually have type V. |
bool has_value | ( | ) | const |
Returns true
if this CacheEntryValue currently contains a value object at all, regardless of whether it is up to date.
There will be no value object after default construction, prior to SetInitialValue().
bool is_cache_entry_disabled | ( | ) | const |
(Advanced) Returns true
if caching is disabled for this cache entry.
This is independent of the out_of_date
flag, and independent of whether the cache is currently frozen.
bool is_out_of_date | ( | ) | const |
Returns true
if the current value is out of date with respect to any of its prerequisites.
This refers only to the out_of_date
flag and is independent of whether caching is enabled or disabled. Don't call this if there is no value here; use has_value() if you aren't sure.
void mark_out_of_date | ( | ) |
(Advanced) Marks the cache entry value as out-of-date with respect to its prerequisites, with no other effects.
In particular, it does not modify the value, does not change the serial number, and does not notify downstream dependents. You should not call this method unless you know that dependent notification has already been taken care of. There are no error conditions; even an empty cache entry can be marked out of date.
void mark_up_to_date | ( | ) |
(Advanced) Marks the cache entry value as up to date with respect to its prerequisites, with no other effects.
That is, this method clears the out_of_date
flag. In particular, this method does not modify the value, does not change the serial number, and does not notify downstream dependents of anything. This is a very dangerous method since it enables access to the value but can't independently determine whether it is really up to date. You should not call it unless you really know what you're doing, or have a death wish. Do not call this method if there is no stored value object; use has_value() if you aren't sure. This is intended to be very fast so doesn't check for a value object except in Debug builds.
bool needs_recomputation | ( | ) | const |
Returns true
if either (a) the value is out of date, or (b) caching is disabled for this entry.
This is a very fast inline method intended to be called every time a cache value is obtained with Eval(). This is equivalent to is_out_of_date() || is_entry_disabled()
but faster. Don't call this if there is no value here; use has_value() if you aren't sure. Note that if this returns true while the cache is frozen, any attempt to access the value will fail since recomputation is forbidden in that case. However, operation of this method is unaffected by whether the cache is frozen.
|
delete |
|
delete |
const AbstractValue& PeekAbstractValueOrThrow | ( | ) | const |
(Advanced) Returns a reference to the contained value without checking whether the value is out of date.
This can be used to check type and size information but should not be used to look at the value unless you really know what you're doing.
std::exception | if there is no contained value. |
const V& PeekValueOrThrow | ( | ) | const |
(Advanced) Convenience method that provides access to the contained value downcast to its known concrete type, without checking whether the value is out of date.
This can be used to check type and size information but should not be used to look at the value unless you really know what you're doing.
std::exception | if there is no contained value, or if the contained value does not actually have type V. |
V | The known actual value type. |
int64_t serial_number | ( | ) | const |
Returns the serial number of the contained value.
This counts up every time the contained value changes, or whenever mutable access is granted.
void set_value | ( | const V & | new_value | ) |
Assigns a new value to a cache entry and marks it up to date.
The cache value must already have a value object of type V to which the new value is assigned, and that value must not already be up to date. The new value is assumed to be up to date with its prerequisites, so the out_of_date
flag is cleared. No out-of-date notifications are issued by this method; we assume downstream dependents were marked out of date at the time this value went out of date. The serial number is incremented. If you are not in a performance-critical situation (and you probably are not!), use SetValueOrThrow<V>()
instead.
std::exception | if the cache is frozen. |
V | The known actual value type. |
void SetInitialValue | ( | std::unique_ptr< AbstractValue > | init_value | ) |
Defines the concrete value type by providing an initial AbstractValue object containing an object of the appropriate concrete type.
This value is marked out of date. It is an error to call this if there is already a value here; use has_value() if you want to check first. Also, the given initial value may not be null. The serial number is set to 1. No out-of-date notifications are sent to downstream dependents. Operation of this initialization method is not affected by whether the cache is currently frozen. However, the corresponding value won't be accessible while the cache remains frozen (since it is out of date).
std::exception | if the given value is null or if there is already a value, or if this CacheEntryValue is malformed in some detectable way. |
void SetValueOrThrow | ( | const V & | new_value | ) |
Assigns a new value to a cache entry and marks it up to date.
The cache entry must already contain a value object of type V to which the new value is assigned, and that value must currently be marked out of date. The supplied new value must have been calculated using the current values in the owning Context, and we assume that here although this method cannot check that assumption. Consequently, this method clears the out_of_date
flag. No out-of-date notifications are issued by this method; we assume downstream dependents were marked out of date at the time this value went out of date. The serial number is incremented.
This method is the safest and most convenient way to assign a new value. However it requires that a new value be computed and then copied into the cache entry, which is fine for small types V but may be too expensive for large ones. You can alternatively obtain a mutable reference to the value already contained in the cache entry and update it in place via GetMutableValueOrThrow().
std::exception | if there is no value, or the value is already up to date, of it doesn't actually have type V. |
std::exception | if the cache is frozen. |
void swap_value | ( | std::unique_ptr< AbstractValue > * | other_value | ) |
(Advanced) Swaps ownership of the stored value object with the given one.
The value is marked out of date and the serial number is incremented. This is useful for discrete updates of abstract state variables that contain large objects. Both values must be non-null and of the same concrete type but we won't check for errors except in Debug builds.
std::exception | if the cache is frozen. |
void ThrowIfBadCacheEntryValue | ( | const internal::ContextMessageInterface * | owning_subcontext = nullptr | ) | const |
Throws an std::exception if there is something clearly wrong with this CacheEntryValue object.
If the owning subcontext is known, provide a pointer to it here and we'll check that this cache entry agrees. In addition we check for other internal inconsistencies.
std::exception | for anything that goes wrong, with an appropriate explanatory message. |
DependencyTicket ticket | ( | ) | const |
Returns the DependencyTicket used to locate the DependencyTracker that manages dependencies for this CacheEntryValue.
The ticket refers to a tracker that is owned by the same subcontext that owns this CacheEntryValue.
|
friend |
|
friend |