// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef TOOLS_GN_INPUT_FILE_MANAGER_H_ #define TOOLS_GN_INPUT_FILE_MANAGER_H_ #include #include #include #include "base/callback.h" #include "base/containers/hash_tables.h" #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" #include "tools/gn/build_settings.h" #include "tools/gn/input_file.h" #include "tools/gn/parse_tree.h" #include "tools/gn/settings.h" class Err; class LocationRange; class ParseNode; class Token; // Manages loading and parsing files from disk. This doesn't actually have // any context for executing the results, so potentially multiple configs // could use the same input file (saving parsing). // // This class is threadsafe. // // InputFile objects must never be deleted while the program is running since // various state points into them. class InputFileManager : public base::RefCountedThreadSafe { public: // Callback issued when a file is laoded. On auccess, the parse node will // refer to the root block of the file. On failure, this will be NULL. typedef base::Callback FileLoadCallback; InputFileManager(); // Loads the given file and executes the callback on the worker pool. // // There are two types of errors. For errors known synchronously, the error // will be set, it will return false, and no work will be scheduled. // // For parse errors and such that happen in the future, the error will be // logged to the scheduler and the callback will be invoked with a null // ParseNode pointer. The given |origin| will be blamed for the invocation. bool AsyncLoadFile(const LocationRange& origin, const BuildSettings* build_settings, const SourceFile& file_name, const FileLoadCallback& callback, Err* err); // Loads and parses the given file synchronously, returning the root block // corresponding to the parsed result. On error, return NULL and the given // Err is set. const ParseNode* SyncLoadFile(const LocationRange& origin, const BuildSettings* build_settings, const SourceFile& file_name, Err* err); // Creates an entry to manage the memory associated with keeping a parsed // set of code in memory. // // The values pointed to by the parameters will be filled with pointers to // the file, tokens, and parse node that this class created. The calling // code is responsible for populating these values and maintaining // threadsafety. This class' only job is to hold onto the memory and delete // it when the program exits. // // This solves the problem that sometimes we need to execute something // dynamic and save the result, but the values all have references to the // nodes and file that created it. Either we need to reset the origin of // the values and lose context for error reporting, or somehow keep the // associated parse nodes, tokens, and file data in memory. This function // allows the latter. void AddDynamicInput(const SourceFile& name, InputFile** file, std::vector** tokens, std::unique_ptr** parse_root); // Does not count dynamic input. int GetInputFileCount() const; // Fills the vector with all input files. void GetAllPhysicalInputFileNames(std::vector* result) const; private: friend class base::RefCountedThreadSafe; struct InputFileData { explicit InputFileData(const SourceFile& file_name); ~InputFileData(); // Don't touch this outside the lock until it's marked loaded. InputFile file; bool loaded; bool sync_invocation; // Lists all invocations that need to be executed when the file completes // loading. std::vector scheduled_callbacks; // Event to signal when the load is complete (or fails). This is lazily // created only when a thread is synchronously waiting for this load (which // only happens for imports). std::unique_ptr completion_event; std::vector tokens; // Null before the file is loaded or if loading failed. std::unique_ptr parsed_root; Err parse_error; }; virtual ~InputFileManager(); void BackgroundLoadFile(const LocationRange& origin, const BuildSettings* build_settings, const SourceFile& name, InputFile* file); // Loads the given file. On error, sets the Err and return false. bool LoadFile(const LocationRange& origin, const BuildSettings* build_settings, const SourceFile& name, InputFile* file, Err* err); mutable base::Lock lock_; // Maps repo-relative filenames to the corresponding owned pointer. typedef base::hash_map> InputFileMap; InputFileMap input_files_; // Tracks all dynamic inputs. The data are holders for memory management // purposes and should not be read or modified by this class. The values // will be vended out to the code creating the dynamic input, who is in // charge of the threadsafety requirements. // // See AddDynamicInput(). std::vector> dynamic_inputs_; DISALLOW_COPY_AND_ASSIGN(InputFileManager); }; #endif // TOOLS_GN_INPUT_FILE_MANAGER_H_