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_SCHEDULER_H_ 6 #define TOOLS_GN_SCHEDULER_H_ 7 8 #include <condition_variable> 9 #include <functional> 10 #include <map> 11 #include <mutex> 12 13 #include "base/atomic_ref_count.h" 14 #include "base/files/file_path.h" 15 #include "base/macros.h" 16 #include "gn/input_file_manager.h" 17 #include "gn/label.h" 18 #include "gn/source_file.h" 19 #include "gn/token.h" 20 #include "util/msg_loop.h" 21 #include "util/worker_pool.h" 22 23 class Target; 24 25 // Maintains the thread pool and error state. 26 class Scheduler { 27 public: 28 Scheduler(); 29 ~Scheduler(); 30 31 bool Run(); 32 task_runner()33 MsgLoop* task_runner() { 34 DCHECK(main_thread_run_loop_); 35 return main_thread_run_loop_; 36 } 37 input_file_manager()38 InputFileManager* input_file_manager() { return input_file_manager_.get(); } 39 verbose_logging()40 bool verbose_logging() const { return verbose_logging_; } set_verbose_logging(bool v)41 void set_verbose_logging(bool v) { verbose_logging_ = v; } 42 43 // TODO(brettw) data race on this access (benign?). is_failed()44 bool is_failed() const { return is_failed_; } 45 46 void Log(const std::string& verb, const std::string& msg); 47 void FailWithError(const Err& err); 48 49 void ScheduleWork(std::function<void()> work); 50 51 void Shutdown(); 52 53 // Declares that the given file was read and affected the build output. 54 // 55 // Some consumers expect provided path to be absolute.kk 56 // 57 // TODO(brettw) this is global rather than per-BuildSettings. If we 58 // start using >1 build settings, then we probably want this to take a 59 // BuildSettings object so we know the depdency on a per-build basis. 60 // If moved, most of the Add/Get functions below should move as well. 61 void AddGenDependency(const base::FilePath& file); 62 std::vector<base::FilePath> GetGenDependencies() const; 63 64 // Tracks calls to write_file for resolving with the unknown generated 65 // inputs (see AddUnknownGeneratedInput below). 66 void AddWrittenFile(const SourceFile& file); 67 68 // Schedules a file to be written due to a target setting write_runtime_deps. 69 void AddWriteRuntimeDepsTarget(const Target* entry); 70 std::vector<const Target*> GetWriteRuntimeDepsTargets() const; 71 bool IsFileGeneratedByWriteRuntimeDeps(const OutputFile& file) const; 72 73 // Tracks generated_file calls. 74 void AddGeneratedFile(const SourceFile& entry); 75 bool IsFileGeneratedByTarget(const SourceFile& file) const; 76 77 // Unknown generated inputs are files that a target declares as an input 78 // in the output directory, but which aren't generated by any dependency. 79 // 80 // Some of these files will be files written by write_file and will be 81 // GenDependencies (see AddWrittenFile above). There are OK and include 82 // things like response files for scripts. Others cases will be ones where 83 // the file is generated by a target that's not a dependency. 84 // 85 // In order to distinguish these two cases, the checking for these input 86 // files needs to be done after all targets are complete. This also has the 87 // nice side effect that if a target generates the file we can find it and 88 // tell the user which dependency is missing. 89 // 90 // The result returned by GetUnknownGeneratedInputs will not count any files 91 // that were written by write_file during execution. 92 void AddUnknownGeneratedInput(const Target* target, const SourceFile& file); 93 std::multimap<SourceFile, const Target*> GetUnknownGeneratedInputs() const; 94 void ClearUnknownGeneratedInputsAndWrittenFiles(); // For testing. 95 96 // We maintain a count of the things we need to do that works like a 97 // refcount. When this reaches 0, the program exits. 98 void IncrementWorkCount(); 99 void DecrementWorkCount(); 100 101 void SuppressOutputForTesting(bool suppress); 102 103 private: 104 void LogOnMainThread(const std::string& verb, const std::string& msg); 105 void FailWithErrorOnMainThread(const Err& err); 106 107 void DoTargetFileWrite(const Target* target); 108 109 void OnComplete(); 110 111 // Waits for tasks scheduled via ScheduleWork() to complete their execution. 112 void WaitForPoolTasks(); 113 114 MsgLoop* main_thread_run_loop_; 115 116 scoped_refptr<InputFileManager> input_file_manager_; 117 118 bool verbose_logging_ = false; 119 120 base::AtomicRefCount work_count_; 121 122 // Number of tasks scheduled by ScheduleWork() that haven't completed their 123 // execution. 124 base::AtomicRefCount pool_work_count_; 125 126 // Lock for |pool_work_count_cv_|. 127 std::mutex pool_work_count_lock_; 128 129 // Condition variable signaled when |pool_work_count_| reaches zero. 130 std::condition_variable pool_work_count_cv_; 131 132 WorkerPool worker_pool_; 133 134 mutable std::mutex lock_; 135 bool is_failed_ = false; 136 137 bool suppress_output_for_testing_ = false; 138 139 // Used to track whether the worker pool has been shutdown. This is necessary 140 // to clean up after tests that make a scheduler but don't run the message 141 // loop. 142 bool has_been_shutdown_ = false; 143 144 // Protected by the lock. See the corresponding Add/Get functions above. 145 std::vector<base::FilePath> gen_dependencies_; 146 std::vector<SourceFile> written_files_; 147 std::vector<const Target*> write_runtime_deps_targets_; 148 std::multimap<SourceFile, const Target*> unknown_generated_inputs_; 149 std::map<SourceFile, bool> generated_files_; 150 151 DISALLOW_COPY_AND_ASSIGN(Scheduler); 152 }; 153 154 extern Scheduler* g_scheduler; 155 156 #endif // TOOLS_GN_SCHEDULER_H_ 157