From 3074c5e1409ad49c0793db6384ecbc6ac4ed33a9 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 11 Dec 2020 07:07:36 +0200 Subject: Add search_locked() versions of search() functions --- libbuild2/algorithm.cxx | 11 +++++++++++ libbuild2/algorithm.hxx | 18 ++++++++++++++++++ libbuild2/algorithm.ixx | 32 ++++++++++++++++++++++++++++++++ libbuild2/search.cxx | 40 ++++++++++++++++++++++++++++++++++++++++ libbuild2/search.hxx | 5 +++++ libbuild2/target.hxx | 4 ++-- 6 files changed, 108 insertions(+), 2 deletions(-) diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx index d1a796d..f859eef 100644 --- a/libbuild2/algorithm.cxx +++ b/libbuild2/algorithm.cxx @@ -68,6 +68,17 @@ namespace build2 return create_new_target (t.ctx, pk); } + pair + search_locked (const target& t, const prerequisite_key& pk) + { + assert (t.ctx.phase == run_phase::match && !pk.proj); + + if (const target* pt = pk.tk.type->search (t, pk)) + return {const_cast (*pt), ulock ()}; + + return create_new_target_locked (t.ctx, pk); + } + const target* search_existing (context& ctx, const prerequisite_key& pk) { diff --git a/libbuild2/algorithm.hxx b/libbuild2/algorithm.hxx index 34e844c..aa1336c 100644 --- a/libbuild2/algorithm.hxx +++ b/libbuild2/algorithm.hxx @@ -39,6 +39,12 @@ namespace build2 LIBBUILD2_SYMEXPORT const target& search (const target&, const prerequisite_key&); + // As above but return the lock if the target was newly created. Note that + // this version can only be used on project-unqualified prerequisites. + // + LIBBUILD2_SYMEXPORT pair + search_locked (const target&, const prerequisite_key&); + // Note that unlike the above version, this one can be called during the // load and execute phases. // @@ -57,6 +63,9 @@ namespace build2 const target& search (const target&, const target_type&, const prerequisite_key&); + pair + search_locked (const target&, const target_type&, const prerequisite_key&); + // As above but specify the prerequisite to search as individual key // components. Scope can be NULL if the directory is absolute. // @@ -70,6 +79,15 @@ namespace build2 const scope* = nullptr, // NULL means dir is absolute. const optional& proj = nullopt); + pair + search_locked (const target&, + const target_type&, + const dir_path& dir, + const dir_path& out, + const string& name, + const string* ext = nullptr, // NULL means unspecified. + const scope* = nullptr); // NULL means dir is absolute. + const target* search_existing (context&, const target_type&, diff --git a/libbuild2/algorithm.ixx b/libbuild2/algorithm.ixx index eb20ad0..396d518 100644 --- a/libbuild2/algorithm.ixx +++ b/libbuild2/algorithm.ixx @@ -34,6 +34,17 @@ namespace build2 k.proj, {&tt, k.tk.dir, k.tk.out, k.tk.name, k.tk.ext}, k.scope}); } + inline pair + search_locked (const target& t, + const target_type& tt, + const prerequisite_key& k) + { + return search_locked ( + t, + prerequisite_key { + k.proj, {&tt, k.tk.dir, k.tk.out, k.tk.name, k.tk.ext}, k.scope}); + } + inline const target& search (const target& t, const target_type& type, @@ -56,6 +67,27 @@ namespace build2 scope}); } + inline pair + search_locked (const target& t, + const target_type& type, + const dir_path& dir, + const dir_path& out, + const string& name, + const string* ext, + const scope* scope) + { + return search_locked ( + t, + prerequisite_key { + nullopt, + { + &type, + &dir, &out, &name, + ext != nullptr ? optional (*ext) : nullopt + }, + scope}); + } + inline const target* search_existing (context& ctx, const target_type& type, diff --git a/libbuild2/search.cxx b/libbuild2/search.cxx index 2b10e0b..b341c85 100644 --- a/libbuild2/search.cxx +++ b/libbuild2/search.cxx @@ -243,4 +243,44 @@ namespace build2 << " for prerequisite " << pk;}); return t; } + + pair + create_new_target_locked (context& ctx, const prerequisite_key& pk) + { + tracer trace ("create_new_target_locked"); + + const target_key& tk (pk.tk); + + // We default to the target in this directory scope. + // + dir_path d; + if (tk.dir->absolute ()) + d = *tk.dir; // Already normalized. + else + { + d = pk.scope->out_path (); + + if (!tk.dir->empty ()) + { + d /= *tk.dir; + d.normalize (); + } + } + + // Find or insert. + // + // @@ OUT: same story as in search_existing_target() re out. + // + auto r (ctx.targets.insert_locked (*tk.type, + move (d), + *tk.out, + *tk.name, + tk.ext, + target_decl::prereq_new, + trace)); + + l5 ([&]{trace << (r.second ? "new" : "existing") << " target " << r.first + << " for prerequisite " << pk;}); + return r; + } } diff --git a/libbuild2/search.hxx b/libbuild2/search.hxx index e63d582..aa30648 100644 --- a/libbuild2/search.hxx +++ b/libbuild2/search.hxx @@ -34,6 +34,11 @@ namespace build2 // LIBBUILD2_SYMEXPORT const target& create_new_target (context&, const prerequisite_key&); + + // As above but return the lock if the target was newly created. + // + LIBBUILD2_SYMEXPORT pair + create_new_target_locked (context&, const prerequisite_key&); } #endif // LIBBUILD2_SEARCH_HXX diff --git a/libbuild2/target.hxx b/libbuild2/target.hxx index d6e128e..e1d91e4 100644 --- a/libbuild2/target.hxx +++ b/libbuild2/target.hxx @@ -1558,8 +1558,8 @@ namespace build2 // (for example, a binless library or an installed import library -- we // know the DLL is there, just not exactly where). In this case you could // also set its mtime to timestamp_unreal (but don't have to, if a real - // timestamp can be derived, for example, the from the import library in - // the DLL case above). + // timestamp can be derived, for example, from the import library in the + // DLL case above). // // Note, however, that a target with timestamp_unreal does not have to // have an empty path. One consequence of this arrangement (assigned path -- cgit v1.1