From 912ac87012ffc2fd0c6fb21823a0244c787ce5ba Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 18 Apr 2022 07:38:22 +0200 Subject: Avoid locking target set if in load phase --- libbuild2/target.hxx | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'libbuild2/target.hxx') diff --git a/libbuild2/target.hxx b/libbuild2/target.hxx index e6622f4..696d5d0 100644 --- a/libbuild2/target.hxx +++ b/libbuild2/target.hxx @@ -1522,7 +1522,7 @@ namespace build2 const dir_path& out, const string& name) const { - slock l (mutex_); + slock l (mutex_, defer_lock); if (ctx.phase != run_phase::load) l.lock (); auto i (map_.find (target_key {&type, &dir, &out, &name, nullopt})); return i != map_.end () ? i->second.get () : nullptr; } @@ -1536,7 +1536,12 @@ namespace build2 // If the target was inserted, keep the map exclusive-locked and return // the lock. In this case, the target is effectively still being created - // since nobody can see it until the lock is released. + // since nobody can see it until the lock is released. Note that there + // is normally quite a bit of contention around this map so make sure to + // not hold the lock longer than absolutely necessary. + // + // If need_lock is false, then release the lock (the target insertion is + // indicated by the presence of the associated mutex). // pair insert_locked (const target_type&, @@ -1545,8 +1550,12 @@ namespace build2 string name, optional ext, target_decl, - tracer&); + tracer&, + bool need_lock = true); + // As above but instead of the lock return an indication of whether the + // target was inserted. + // pair insert (const target_type& tt, dir_path dir, @@ -1562,9 +1571,10 @@ namespace build2 move (name), move (ext), decl, - t)); + t, + false)); - return pair (p.first, p.second.owns_lock ()); // Clang 3.7 + return pair (p.first, p.second.mutex () != nullptr); } // Note that the following versions always enter implied targets. -- cgit v1.1