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 |