diff options
Diffstat (limited to 'build2/variable')
-rw-r--r-- | build2/variable | 107 |
1 files changed, 58 insertions, 49 deletions
diff --git a/build2/variable b/build2/variable index 35530ca..10f4ac9 100644 --- a/build2/variable +++ b/build2/variable @@ -1036,7 +1036,7 @@ namespace build2 using value::value; using value::operator=; - size_t version = 0; // Incremented on each modification (override cache). + size_t version = 0; // Incremented on each modification (variable_cache). size_t generation; // load_generation of this value (global state only). }; @@ -1167,6 +1167,57 @@ namespace build2 map_type m_; }; + // Value caching. Used for overrides as well as target type/pattern-specific + // append/prepend. + // + // In many places we assume that we can store a reference to the returned + // variable value (e.g., install::lookup_install()). As a result, in these + // cases where we calculate the value dynamically, we have to cache it + // (note, however, that if the value becomes stale, there is no guarantee + // the references remain valid). + // + // Note that since the cache can be modified on any lookup (including during + // the execute phase), it is protected by its own mutex shard (allocated in + // main()). + // + extern size_t variable_cache_mutex_shard_size; + extern unique_ptr<shared_mutex[]> variable_cache_mutex_shard; + + template <typename K> + class variable_cache + { + public: + // If the returned unique lock is locked, then the value has been + // invalidated. + // + pair<value&, ulock> + insert (K, const lookup& stem, size_t version); + + private: + struct entry_type + { + // Note: we use value_data instead of value since the result is often + // returned as lookup. We also maintain the version in case one cached + // value (e.g., override) is based on another (e.g., target + // type/pattern-specific prepend/append). + // + variable_map::value_data value; + + size_t version = 0; // Version on which this value is based. + + // Location of the stem as well as the version on which this cache + // value is based. Used to track the location and value of the stem + // for cache invalidation. NULL/0 means there is no stem. + // + const variable_map* stem_vars = nullptr; + size_t stem_version = 0; + }; + + using map_type = std::map<K, entry_type>; + + map_type m_; + }; + // Target type/pattern-specific variables. // class variable_pattern_map @@ -1219,65 +1270,23 @@ namespace build2 lookup find (const target_type&, const string& tname, const variable&) const; - + // Prepend/append value cache. // // The key is the combination of the "original value identity" (as a // pointer to the value in one of the variable_pattern_map's) and the // "target identity" (as target type and target name). Note that while at // first it may seem like we don't need the target identity, we actually - // do since the stem may itself be target-type/pattern-specific. - // - // @@ MT + // do since the stem may itself be target-type/pattern-specific. See + // scope::find_original() for details. // - mutable std::map<tuple<const value*, const target_type*, string>, - variable_map::value_data> cache; + mutable + variable_cache<tuple<const value*, const target_type*, string>> + cache; private: bool global_; map_type map_; }; - - // Value caching. Used for overrides as well as target type/pattern-specific - // append/prepend. - // - // In many places we assume that we can store a reference to the returned - // variable value (e.g., install::lookup_install()). As a result, in these - // cases where we calculate the value dynamically, we have to cache it - // (note, however, that if the value becomes stale, there is no guarantee - // the references remain valid). - // - template <typename K> - class variable_cache - { - public: - // If the returned unique lock is locked, then the value has been - // invalidated. - // - pair<value&, ulock> - insert (K, const lookup& stem); - - private: - struct entry_type - { - build2::value value; - - // Location of the stem as well as the version on which this cache - // value is based. Used to track the location and value of the stem - // for cache invalidation. NULL/0 means there is no stem. - // - const variable_map* stem_vars = nullptr; - size_t stem_version = 0; - }; - - using map_type = std::map<K, entry_type>; - - map_type m_; - }; - - // Allocated in main(). - // - extern size_t variable_cache_mutex_shard_size; - extern unique_ptr<shared_mutex[]> variable_cache_mutex_shard; } #include <build2/variable.ixx> |