aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2024-11-04 07:44:34 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2024-11-04 07:44:34 +0200
commit74c9269e1363e33e4b3223a029049a13e6595e7e (patch)
tree1d360d56c9f04e976e8ed5700fe0fde0a1dd420b
parent95da67852e7c837592a61fb44cd8acd325d16ba2 (diff)
Redo group_prerequisites to use snapshots of prerequisites (GH issue #408)
It turns out both target and group prerequisites can be replaced during dependency synthesis in more obscure cases.
-rw-r--r--libbuild2/prerequisite.cxx4
-rw-r--r--libbuild2/prerequisite.hxx2
-rw-r--r--libbuild2/target.cxx2
-rw-r--r--libbuild2/target.hxx18
-rw-r--r--libbuild2/target.ixx60
5 files changed, 54 insertions, 32 deletions
diff --git a/libbuild2/prerequisite.cxx b/libbuild2/prerequisite.cxx
index bb77c9e..ec18665 100644
--- a/libbuild2/prerequisite.cxx
+++ b/libbuild2/prerequisite.cxx
@@ -91,4 +91,8 @@ namespace build2
return r;
}
+
+ // prerequisites
+ //
+ const prerequisites empty_prerequisites;
}
diff --git a/libbuild2/prerequisite.hxx b/libbuild2/prerequisite.hxx
index 9b9cccf..008fc11 100644
--- a/libbuild2/prerequisite.hxx
+++ b/libbuild2/prerequisite.hxx
@@ -190,6 +190,8 @@ namespace build2
}
using prerequisites = vector<prerequisite>;
+
+ LIBBUILD2_SYMEXPORT extern const prerequisites empty_prerequisites;
}
#endif // LIBBUILD2_PREREQUISITE_HXX
diff --git a/libbuild2/target.cxx b/libbuild2/target.cxx
index 65e18d3..b915b25 100644
--- a/libbuild2/target.cxx
+++ b/libbuild2/target.cxx
@@ -76,8 +76,6 @@ namespace build2
// target
//
- const target::prerequisites_type target::empty_prerequisites_;
-
target::
~target ()
{
diff --git a/libbuild2/target.hxx b/libbuild2/target.hxx
index ae45082..1b7b755 100644
--- a/libbuild2/target.hxx
+++ b/libbuild2/target.hxx
@@ -733,8 +733,6 @@ namespace build2
atomic<uint8_t> prerequisites_state_ {0};
prerequisites_type prerequisites_;
- static const prerequisites_type empty_prerequisites_;
-
// Target-specific variables.
//
// See also rule-specific variables below.
@@ -1488,9 +1486,9 @@ namespace build2
{
public:
explicit
- group_prerequisites (const target& t);
+ group_prerequisites (const target&);
- group_prerequisites (const target& t, const target* g);
+ group_prerequisites (const target&, const target* group);
using prerequisites_type = target::prerequisites_type;
using base_iterator = prerequisites_type::const_iterator;
@@ -1504,8 +1502,8 @@ namespace build2
using iterator_category = std::bidirectional_iterator_tag;
iterator () {}
- iterator (const target* t,
- const target* g,
+ iterator (const prerequisites_type* t,
+ const prerequisites_type* g,
const prerequisites_type* c,
base_iterator i): t_ (t), g_ (g), c_ (c), i_ (i) {}
@@ -1534,8 +1532,8 @@ namespace build2
operator!= (const iterator& x, const iterator& y) {return !(x == y);}
private:
- const target* t_ = nullptr;
- const target* g_ = nullptr;
+ const prerequisites_type* t_ = nullptr;
+ const prerequisites_type* g_ = nullptr;
const prerequisites_type* c_ = nullptr;
base_iterator i_;
};
@@ -1558,8 +1556,8 @@ namespace build2
size () const;
private:
- const target& t_;
- const target* g_;
+ const prerequisites_type* t_; // NULL if empty.
+ const prerequisites_type* g_; // NULL if no group or empty.
};
// A member of a prerequisite. If 'member' is NULL, then this is the
diff --git a/libbuild2/target.ixx b/libbuild2/target.ixx
index f8ee975..1dc667d 100644
--- a/libbuild2/target.ixx
+++ b/libbuild2/target.ixx
@@ -207,7 +207,7 @@ namespace build2
{
return prerequisites_state_.load (memory_order_acquire) == 2
? prerequisites_
- : empty_prerequisites_;
+ : empty_prerequisites;
}
inline bool target::
@@ -491,44 +491,64 @@ namespace build2
//
inline group_prerequisites::
group_prerequisites (const target& t)
- : t_ (t), g_ (nullptr)
+ : t_ (nullptr), g_ (nullptr)
{
- if (const target* g = t_.group)
+ // Take "snapshot" of prerequisites, both for target and group.
+ //
+ const auto& ps (t.prerequisites ());
+ if (!ps.empty ())
+ t_ = &ps;
+
+ if (const target* g = t.group)
{
- if (g->adhoc_member == nullptr && // Not ad hoc group member.
- !g->prerequisites ().empty ())
- g_ = g;
+ if (g->adhoc_member == nullptr) // Not ad hoc group member.
+ {
+ const auto& ps (g->prerequisites ());
+ if (!ps.empty ())
+ g_ = &ps;
+ }
}
}
inline group_prerequisites::
group_prerequisites (const target& t, const target* g)
- : t_ (t),
- g_ (g == nullptr ||
- g->prerequisites ().empty ()
- ? nullptr : g)
+ : t_ (nullptr), g_ (nullptr)
{
+ const auto& ps (t.prerequisites ());
+ if (!ps.empty ())
+ t_ = &ps;
+
+ if (g != nullptr)
+ {
+ const auto& ps (g->prerequisites ());
+ if (!ps.empty ())
+ g_ = &ps;
+ }
}
inline auto group_prerequisites::
begin () const -> iterator
{
- auto& c ((g_ != nullptr ? *g_ : t_).prerequisites ());
- return iterator (&t_, g_, &c, c.begin ());
+ auto* c (g_ != nullptr ? g_ :
+ t_ != nullptr ? t_ :
+ &empty_prerequisites);
+ return iterator (t_, g_, c, c->begin ());
}
inline auto group_prerequisites::
end () const -> iterator
{
- auto& c (t_.prerequisites ());
- return iterator (&t_, g_, &c, c.end ());
+ auto* c (t_ != nullptr ? t_ :
+ g_ != nullptr ? g_ :
+ &empty_prerequisites);
+ return iterator (t_, g_, c, c->end ());
}
inline size_t group_prerequisites::
size () const
{
- return t_.prerequisites ().size () +
- (g_ != nullptr ? g_->prerequisites ().size () : 0);
+ return ((t_ != nullptr ? t_->size () : 0) +
+ (g_ != nullptr ? g_->size () : 0));
}
// group_prerequisites::iterator
@@ -536,9 +556,9 @@ namespace build2
inline auto group_prerequisites::iterator::
operator++ () -> iterator&
{
- if (++i_ == c_->end () && c_ != &t_->prerequisites ())
+ if (++i_ == c_->end () && c_ == g_ && t_ != nullptr)
{
- c_ = &t_->prerequisites ();
+ c_ = t_;
i_ = c_->begin ();
}
return *this;
@@ -548,9 +568,9 @@ namespace build2
inline auto group_prerequisites::iterator::
operator-- () -> iterator&
{
- if (i_ == c_->begin () && c_ == &t_->prerequisites ())
+ if (i_ == c_->begin () && c_ == t_)
{
- c_ = &g_->prerequisites ();
+ c_ = g_;
i_ = c_->end ();
}