Adding wrapper class WKBackForwardListItemHolder
[chromium-blink-merge.git] / tools / gn / scheduler.cc
blob622019ef05635af0769107e0f7fa4e01ae31d451
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.
5 #include "tools/gn/scheduler.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "tools/gn/standard_out.h"
11 #include "tools/gn/switches.h"
13 Scheduler* g_scheduler = nullptr;
15 namespace {
17 int GetThreadCount() {
18 std::string thread_count =
19 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
20 switches::kThreads);
22 int result;
23 if (thread_count.empty() || !base::StringToInt(thread_count, &result))
24 return 32;
25 return result;
28 } // namespace
30 Scheduler::Scheduler()
31 : pool_(new base::SequencedWorkerPool(GetThreadCount(), "worker_")),
32 input_file_manager_(new InputFileManager),
33 verbose_logging_(false),
34 work_count_(0),
35 is_failed_(false),
36 has_been_shutdown_(false) {
37 g_scheduler = this;
40 Scheduler::~Scheduler() {
41 if (!has_been_shutdown_)
42 pool_->Shutdown();
43 g_scheduler = nullptr;
46 bool Scheduler::Run() {
47 runner_.Run();
48 bool local_is_failed;
50 base::AutoLock lock(lock_);
51 local_is_failed = is_failed();
52 has_been_shutdown_ = true;
54 // Don't do this inside the lock since it will block on the workers, which
55 // may be in turn waiting on the lock.
56 pool_->Shutdown();
57 return !local_is_failed;
60 void Scheduler::Log(const std::string& verb, const std::string& msg) {
61 if (base::MessageLoop::current() == &main_loop_) {
62 LogOnMainThread(verb, msg);
63 } else {
64 // The run loop always joins on the sub threads, so the lifetime of this
65 // object outlives the invocations of this function, hence "unretained".
66 main_loop_.PostTask(FROM_HERE,
67 base::Bind(&Scheduler::LogOnMainThread,
68 base::Unretained(this), verb, msg));
72 void Scheduler::FailWithError(const Err& err) {
73 DCHECK(err.has_error());
75 base::AutoLock lock(lock_);
77 if (is_failed_ || has_been_shutdown_)
78 return; // Ignore errors once we see one.
79 is_failed_ = true;
82 if (base::MessageLoop::current() == &main_loop_) {
83 FailWithErrorOnMainThread(err);
84 } else {
85 // The run loop always joins on the sub threads, so the lifetime of this
86 // object outlives the invocations of this function, hence "unretained".
87 main_loop_.PostTask(FROM_HERE,
88 base::Bind(&Scheduler::FailWithErrorOnMainThread,
89 base::Unretained(this), err));
93 void Scheduler::ScheduleWork(const base::Closure& work) {
94 IncrementWorkCount();
95 pool_->PostWorkerTaskWithShutdownBehavior(
96 FROM_HERE, base::Bind(&Scheduler::DoWork,
97 base::Unretained(this), work),
98 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
101 void Scheduler::AddGenDependency(const base::FilePath& file) {
102 base::AutoLock lock(lock_);
103 gen_dependencies_.push_back(file);
106 std::vector<base::FilePath> Scheduler::GetGenDependencies() const {
107 base::AutoLock lock(lock_);
108 return gen_dependencies_;
111 void Scheduler::AddWrittenFile(const SourceFile& file) {
112 base::AutoLock lock(lock_);
113 written_files_.push_back(file);
116 void Scheduler::AddUnknownGeneratedInput(const Target* target,
117 const SourceFile& file) {
118 base::AutoLock lock(lock_);
119 unknown_generated_inputs_.insert(std::make_pair(file, target));
122 std::multimap<SourceFile, const Target*>
123 Scheduler::GetUnknownGeneratedInputs() const {
124 base::AutoLock lock(lock_);
126 // Remove all unknown inputs that were written files. These are OK as inputs
127 // to build steps since they were written as a side-effect of running GN.
129 // It's assumed that this function is called once during cleanup to check for
130 // errors, so performing this work in the lock doesn't matter.
131 std::multimap<SourceFile, const Target*> filtered = unknown_generated_inputs_;
132 for (const SourceFile& file : written_files_)
133 filtered.erase(file);
135 return filtered;
138 void Scheduler::ClearUnknownGeneratedInputsAndWrittenFiles() {
139 base::AutoLock lock(lock_);
140 unknown_generated_inputs_.clear();
141 written_files_.clear();
144 void Scheduler::IncrementWorkCount() {
145 base::AtomicRefCountInc(&work_count_);
148 void Scheduler::DecrementWorkCount() {
149 if (!base::AtomicRefCountDec(&work_count_)) {
150 if (base::MessageLoop::current() == &main_loop_) {
151 OnComplete();
152 } else {
153 main_loop_.PostTask(FROM_HERE,
154 base::Bind(&Scheduler::OnComplete,
155 base::Unretained(this)));
160 void Scheduler::LogOnMainThread(const std::string& verb,
161 const std::string& msg) {
162 OutputString(verb, DECORATION_YELLOW);
163 OutputString(" " + msg + "\n");
166 void Scheduler::FailWithErrorOnMainThread(const Err& err) {
167 err.PrintToStdout();
168 runner_.Quit();
171 void Scheduler::DoWork(const base::Closure& closure) {
172 closure.Run();
173 DecrementWorkCount();
176 void Scheduler::OnComplete() {
177 // Should be called on the main thread.
178 DCHECK(base::MessageLoop::current() == main_loop());
179 runner_.Quit();