OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "tools/gn/import_manager.h" |
| 6 |
| 7 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/stl_util.h" |
| 9 #include "tools/gn/parse_tree.h" |
| 10 #include "tools/gn/scheduler.h" |
| 11 |
| 12 namespace { |
| 13 |
| 14 // Returns a newly-allocated scope on success, null on failure. |
| 15 Scope* UncachedImport(const Settings* settings, |
| 16 const SourceFile& file, |
| 17 const ParseNode* node_for_err, |
| 18 Err* err) { |
| 19 const ParseNode* node = g_scheduler->input_file_manager()->SyncLoadFile( |
| 20 node_for_err->GetRange(), settings->build_settings(), file, err); |
| 21 if (!node) |
| 22 return NULL; |
| 23 const BlockNode* block = node->AsBlock(); |
| 24 CHECK(block); |
| 25 |
| 26 scoped_ptr<Scope> scope(new Scope(settings->base_config())); |
| 27 scope->SetProcessingImport(); |
| 28 block->ExecuteBlockInScope(scope.get(), err); |
| 29 if (err->has_error()) |
| 30 return NULL; |
| 31 scope->ClearProcessingImport(); |
| 32 |
| 33 return scope.release(); |
| 34 } |
| 35 |
| 36 } // namesapce |
| 37 |
| 38 ImportManager::ImportManager() { |
| 39 } |
| 40 |
| 41 ImportManager::~ImportManager() { |
| 42 STLDeleteContainerPairSecondPointers(imports_.begin(), imports_.end()); |
| 43 } |
| 44 |
| 45 bool ImportManager::DoImport(const SourceFile& file, |
| 46 const ParseNode* node_for_err, |
| 47 Scope* scope, |
| 48 Err* err) { |
| 49 // See if we have a cached import, but be careful to actually do the scope |
| 50 // copying outside of the lock. |
| 51 const Scope* imported_scope = NULL; |
| 52 { |
| 53 base::AutoLock lock(lock_); |
| 54 ImportMap::const_iterator found = imports_.find(file); |
| 55 if (found != imports_.end()) |
| 56 imported_scope = found->second; |
| 57 } |
| 58 |
| 59 if (!imported_scope) { |
| 60 // Do a new import of the file. |
| 61 imported_scope = UncachedImport(scope->settings(), file, |
| 62 node_for_err, err); |
| 63 if (!imported_scope) |
| 64 return false; |
| 65 |
| 66 // We loaded the file outside the lock. This means that there could be a |
| 67 // race and the file was already loaded on a background thread. Recover |
| 68 // from this and use the existing one if that happens. |
| 69 { |
| 70 base::AutoLock lock(lock_); |
| 71 ImportMap::const_iterator found = imports_.find(file); |
| 72 if (found != imports_.end()) { |
| 73 delete imported_scope; |
| 74 imported_scope = found->second; |
| 75 } else { |
| 76 imports_[file] = imported_scope; |
| 77 } |
| 78 } |
| 79 } |
| 80 |
| 81 return imported_scope->NonRecursiveMergeTo(scope, node_for_err, |
| 82 "import", err); |
| 83 } |
OLD | NEW |