Home | History | Annotate | Download | only in gn
      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