From 63f6a8256e3f9fb47cb941be63baa70e2be48d3b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 2 Feb 2017 15:35:44 +0200 Subject: Implement target_set locking, including extension update --- build2/target | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'build2/target') diff --git a/build2/target b/build2/target index fc6e782..1a300f7 100644 --- a/build2/target +++ b/build2/target @@ -107,6 +107,8 @@ namespace build2 // class target { + optional* ext_; // Reference to value in target_key. + public: using action_type = build2::action; @@ -127,9 +129,9 @@ namespace build2 const dir_path dir; // Absolute and normalized. const dir_path out; // Empty or absolute and normalized. const string name; - optional ext () const {return *ext_;} - optional* ext_; // Reference to value in target_key. + const string* ext () const; // Return NULL if not specified. + const string& ext (string); const dir_path& out_dir () const {return out.empty () ? dir : out;} @@ -247,11 +249,11 @@ namespace build2 virtual group_view group_members (action_type) const; - // Note that the returned key "tracks" the target; that is, any updates - // to the targets's members will be reflected in the key. + // Note that the returned key "tracks" the target (except for the + // extension). // target_key - key () const {return target_key {&type (), &dir, &out, &name, ext ()};} + key () const; // Scoping. // @@ -382,7 +384,10 @@ namespace build2 // A target that is not (yet) entered as part of a real dependency // declaration (for example, that is entered as part of a target-specific - // variable assignment) is called implied. + // variable assignment, dependency extraction, etc) is called implied. + // + // The implied flag should only be cleared during the load phase via the + // target_set::insert(). // public: bool implied; @@ -1000,8 +1005,10 @@ namespace build2 T* find (const dir_path& dir, const dir_path& out, const string& name) const { - auto i (map_.find ( - target_key {&T::static_type, &dir, &out, &name, nullopt})); + slock l (mutex_); + auto i ( + map_.find ( + target_key {&T::static_type, &dir, &out, &name, nullopt})); return i != map_.end () ? static_cast (i->second.get ()) : nullptr; } @@ -1014,6 +1021,8 @@ namespace build2 bool implied, tracer&); + // Note that the following versions always enter implied targets. + // template T& insert (const target_type& tt, @@ -1029,7 +1038,7 @@ namespace build2 move (out), move (name), move (ext), - false, // Always real (not implied). + true, t).first); } @@ -1042,7 +1051,7 @@ namespace build2 tracer& t) { return static_cast ( - insert (T::static_type, dir, out, name, ext, false, t).first); + insert (T::static_type, dir, out, name, ext, true, t).first); } template @@ -1053,7 +1062,7 @@ namespace build2 tracer& t) { return static_cast ( - insert (T::static_type, dir, out, name, nullopt, false, t).first); + insert (T::static_type, dir, out, name, nullopt, true, t).first); } // Note: not MT-safe so can only be used during serial execution. @@ -1068,6 +1077,9 @@ namespace build2 clear () {map_.clear ();} private: + friend class target; // Access to mutex. + + mutable shared_mutex mutex_; map_type map_; }; -- cgit v1.1