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