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 #ifndef TOOLS_GN_INPUT_FILE_MANAGER_H_ 6 #define TOOLS_GN_INPUT_FILE_MANAGER_H_ 7 8 #include <set> 9 #include <utility> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/callback.h" 14 #include "base/containers/hash_tables.h" 15 #include "base/files/file_path.h" 16 #include "base/memory/ref_counted.h" 17 #include "base/synchronization/lock.h" 18 #include "base/synchronization/waitable_event.h" 19 #include "tools/gn/build_settings.h" 20 #include "tools/gn/input_file.h" 21 #include "tools/gn/parse_tree.h" 22 #include "tools/gn/settings.h" 23 24 class Err; 25 class LocationRange; 26 class ParseNode; 27 class Token; 28 29 // Manages loading and parsing files from disk. This doesn't actually have 30 // any context for executing the results, so potentially multiple configs 31 // could use the same input file (saving parsing). 32 // 33 // This class is threadsafe. 34 // 35 // InputFile objects must never be deleted while the program is running since 36 // various state points into them. 37 class InputFileManager : public base::RefCountedThreadSafe<InputFileManager> { 38 public: 39 // Callback issued when a file is laoded. On auccess, the parse node will 40 // refer to the root block of the file. On failure, this will be NULL. 41 typedef base::Callback<void(const ParseNode*)> FileLoadCallback; 42 43 InputFileManager(); 44 45 // Loads the given file and executes the callback on the worker pool. 46 // 47 // There are two types of errors. For errors known synchronously, the error 48 // will be set, it will return false, and no work will be scheduled. 49 // 50 // For parse errors and such that happen in the future, the error will be 51 // logged to the scheduler and the callback will be invoked with a null 52 // ParseNode pointer. The given |origin| will be blamed for the invocation. 53 bool AsyncLoadFile(const LocationRange& origin, 54 const BuildSettings* build_settings, 55 const SourceFile& file_name, 56 const FileLoadCallback& callback, 57 Err* err); 58 59 // Loads and parses the given file synchronously, returning the root block 60 // corresponding to the parsed result. On error, return NULL and the given 61 // Err is set. 62 const ParseNode* SyncLoadFile(const LocationRange& origin, 63 const BuildSettings* build_settings, 64 const SourceFile& file_name, 65 Err* err); 66 67 // Creates an entry to manage the memory associated with keeping a parsed 68 // set of code in memory. 69 // 70 // The values pointed to by the parameters will be filled with pointers to 71 // the file, tokens, and parse node that this class created. The calling 72 // code is responsible for populating these values and maintaining 73 // threadsafety. This class' only job is to hold onto the memory and delete 74 // it when the program exits. 75 // 76 // This solves the problem that sometimes we need to execute something 77 // dynamic and save the result, but the values all have references to the 78 // nodes and file that created it. Either we need to reset the origin of 79 // the values and lose context for error reporting, or somehow keep the 80 // associated parse nodes, tokens, and file data in memory. This function 81 // allows the latter. 82 void AddDynamicInput(const SourceFile& name, 83 InputFile** file, 84 std::vector<Token>** tokens, 85 scoped_ptr<ParseNode>** parse_root); 86 87 // Does not count dynamic input. 88 int GetInputFileCount() const; 89 90 // Fills the vector with all input files. 91 void GetAllPhysicalInputFileNames(std::vector<base::FilePath>* result) const; 92 93 private: 94 friend class base::RefCountedThreadSafe<InputFileManager>; 95 96 struct InputFileData { 97 InputFileData(const SourceFile& file_name); 98 ~InputFileData(); 99 100 // Don't touch this outside the lock until it's marked loaded. 101 InputFile file; 102 103 bool loaded; 104 105 bool sync_invocation; 106 107 // Lists all invocations that need to be executed when the file completes 108 // loading. 109 std::vector<FileLoadCallback> scheduled_callbacks; 110 111 // Event to signal when the load is complete (or fails). This is lazily 112 // created only when a thread is synchronously waiting for this load (which 113 // only happens for imports). 114 scoped_ptr<base::WaitableEvent> completion_event; 115 116 std::vector<Token> tokens; 117 118 // Null before the file is loaded or if loading failed. 119 scoped_ptr<ParseNode> parsed_root; 120 }; 121 122 virtual ~InputFileManager(); 123 124 void BackgroundLoadFile(const LocationRange& origin, 125 const BuildSettings* build_settings, 126 const SourceFile& name, 127 InputFile* file); 128 129 // Loads the given file. On error, sets the Err and return false. 130 bool LoadFile(const LocationRange& origin, 131 const BuildSettings* build_settings, 132 const SourceFile& name, 133 InputFile* file, 134 Err* err); 135 136 mutable base::Lock lock_; 137 138 // Maps repo-relative filenames to the corresponding owned pointer. 139 typedef base::hash_map<SourceFile, InputFileData*> InputFileMap; 140 InputFileMap input_files_; 141 142 // Tracks all dynamic inputs. The data are holders for memory management 143 // purposes and should not be read or modified by this class. The values 144 // will be vended out to the code creating the dynamic input, who is in 145 // charge of the threadsafety requirements. 146 // 147 // See AddDynamicInput(). 148 // 149 // Owning pointers. 150 std::vector<InputFileData*> dynamic_inputs_; 151 152 DISALLOW_COPY_AND_ASSIGN(InputFileManager); 153 }; 154 155 #endif // TOOLS_GN_INPUT_FILE_MANAGER_H_ 156