Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(233)

Unified Diff: tools/gn/import_manager.cc

Issue 1957483004: GN: Don't import a file more than once. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: typo Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/gn/import_manager.h ('k') | tools/gn/scheduler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/gn/import_manager.cc
diff --git a/tools/gn/import_manager.cc b/tools/gn/import_manager.cc
index 86cfd458a9cbb619a394a35b4ddc54e30736d9ee..a1555b994541f9aa735c4491c3ea13c2227fd761 100644
--- a/tools/gn/import_manager.cc
+++ b/tools/gn/import_manager.cc
@@ -4,6 +4,7 @@
#include "tools/gn/import_manager.h"
+#include "tools/gn/err.h"
#include "tools/gn/parse_tree.h"
#include "tools/gn/scheduler.h"
#include "tools/gn/scope_per_file_provider.h"
@@ -41,7 +42,23 @@ std::unique_ptr<Scope> UncachedImport(const Settings* settings,
return scope;
}
-} // namesapce
+} // namespace
+
+struct ImportManager::ImportInfo {
+ ImportInfo() {}
+ ~ImportInfo() {}
+
+ // This lock protects the unique_ptr. Once the scope is computed,
+ // it is const and can be accessed read-only outside of the lock.
+ base::Lock load_lock;
+
+ std::unique_ptr<const Scope> scope;
+
+ // The result of loading the import. If the load failed, the scope will be
+ // null but this will be set to error. In this case the thread should not
+ // attempt to load the file, even if the scope is null.
+ Err load_result;
+};
ImportManager::ImportManager() {
}
@@ -55,39 +72,42 @@ bool ImportManager::DoImport(const SourceFile& file,
Err* err) {
// See if we have a cached import, but be careful to actually do the scope
// copying outside of the lock.
- const Scope* imported_scope = nullptr;
+ ImportInfo* import_info = nullptr;
{
- base::AutoLock lock(lock_);
- ImportMap::const_iterator found = imports_.find(file);
- if (found != imports_.end())
- imported_scope = found->second.get();
+ base::AutoLock lock(imports_lock_);
+ std::unique_ptr<ImportInfo>& info_ptr = imports_[file];
+ if (!info_ptr)
+ info_ptr.reset(new ImportInfo);
+
+ // Promote the ImportInfo to outside of the imports lock.
+ import_info = info_ptr.get();
}
- if (!imported_scope) {
- // Do a new import of the file.
- std::unique_ptr<Scope> new_imported_scope =
- UncachedImport(scope->settings(), file, node_for_err, err);
- if (!new_imported_scope)
- return false;
-
- // We loaded the file outside the lock. This means that there could be a
- // race and the file was already loaded on a background thread. Recover
- // from this and use the existing one if that happens.
- {
- base::AutoLock lock(lock_);
- ImportMap::const_iterator found = imports_.find(file);
- if (found != imports_.end()) {
- imported_scope = found->second.get();
- } else {
- imported_scope = new_imported_scope.get();
- imports_[file] = std::move(new_imported_scope);
+ // Now use the per-import-file lock to block this thread if another thread
+ // is already processing the import.
+ const Scope* import_scope = nullptr;
+ {
+ base::AutoLock lock(import_info->load_lock);
+
+ if (!import_info->scope) {
+ // Only load if the import hasn't already failed.
+ if (!import_info->load_result.has_error()) {
+ import_info->scope = UncachedImport(
+ scope->settings(), file, node_for_err, &import_info->load_result);
+ }
+ if (import_info->load_result.has_error()) {
+ *err = import_info->load_result;
+ return false;
}
}
+
+ // Promote the now-read-only scope to outside the load lock.
+ import_scope = import_info->scope.get();
}
Scope::MergeOptions options;
options.skip_private_vars = true;
options.mark_dest_used = true; // Don't require all imported values be used.
- return imported_scope->NonRecursiveMergeTo(scope, options, node_for_err,
- "import", err);
+ return import_scope->NonRecursiveMergeTo(scope, options, node_for_err,
+ "import", err);
}
« no previous file with comments | « tools/gn/import_manager.h ('k') | tools/gn/scheduler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698