Created a <webview> find API.
[chromium-blink-merge.git] / tools / gn / scheduler.cc
blob81ca60e9191a1008af829e158f056af9aae607b1
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"
12 Scheduler* g_scheduler = NULL;
14 namespace {
16 int GetThreadCount() {
17 std::string thread_count =
18 CommandLine::ForCurrentProcess()->GetSwitchValueASCII("threads");
20 int result;
21 if (thread_count.empty() || !base::StringToInt(thread_count, &result))
22 return 32;
23 return result;
26 } // namespace
28 Scheduler::Scheduler()
29 : pool_(new base::SequencedWorkerPool(GetThreadCount(), "worker_")),
30 input_file_manager_(new InputFileManager),
31 verbose_logging_(false),
32 work_count_(0),
33 is_failed_(false),
34 has_been_shutdown_(false) {
35 g_scheduler = this;
38 Scheduler::~Scheduler() {
39 if (!has_been_shutdown_)
40 pool_->Shutdown();
41 g_scheduler = NULL;
44 bool Scheduler::Run() {
45 runner_.Run();
46 bool local_is_failed;
48 base::AutoLock lock(lock_);
49 local_is_failed = is_failed();
50 has_been_shutdown_ = true;
52 // Don't do this inside the lock since it will block on the workers, which
53 // may be in turn waiting on the lock.
54 pool_->Shutdown();
55 return !local_is_failed;
58 void Scheduler::Log(const std::string& verb, const std::string& msg) {
59 if (base::MessageLoop::current() == &main_loop_) {
60 LogOnMainThread(verb, msg);
61 } else {
62 // The run loop always joins on the sub threads, so the lifetime of this
63 // object outlives the invocations of this function, hence "unretained".
64 main_loop_.PostTask(FROM_HERE,
65 base::Bind(&Scheduler::LogOnMainThread,
66 base::Unretained(this), verb, msg));
70 void Scheduler::FailWithError(const Err& err) {
71 DCHECK(err.has_error());
73 base::AutoLock lock(lock_);
75 if (is_failed_ || has_been_shutdown_)
76 return; // Ignore errors once we see one.
77 is_failed_ = true;
80 if (base::MessageLoop::current() == &main_loop_) {
81 FailWithErrorOnMainThread(err);
82 } else {
83 // The run loop always joins on the sub threads, so the lifetime of this
84 // object outlives the invocations of this function, hence "unretained".
85 main_loop_.PostTask(FROM_HERE,
86 base::Bind(&Scheduler::FailWithErrorOnMainThread,
87 base::Unretained(this), err));
91 void Scheduler::ScheduleWork(const base::Closure& work) {
92 IncrementWorkCount();
93 pool_->PostWorkerTaskWithShutdownBehavior(
94 FROM_HERE, base::Bind(&Scheduler::DoWork,
95 base::Unretained(this), work),
96 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
99 void Scheduler::AddGenDependency(const base::FilePath& file) {
100 base::AutoLock lock(lock_);
101 gen_dependencies_.push_back(file);
104 std::vector<base::FilePath> Scheduler::GetGenDependencies() const {
105 base::AutoLock lock(lock_);
106 return gen_dependencies_;
109 void Scheduler::IncrementWorkCount() {
110 base::AtomicRefCountInc(&work_count_);
113 void Scheduler::DecrementWorkCount() {
114 if (!base::AtomicRefCountDec(&work_count_)) {
115 if (base::MessageLoop::current() == &main_loop_) {
116 OnComplete();
117 } else {
118 main_loop_.PostTask(FROM_HERE,
119 base::Bind(&Scheduler::OnComplete,
120 base::Unretained(this)));
125 void Scheduler::LogOnMainThread(const std::string& verb,
126 const std::string& msg) {
127 OutputString(verb, DECORATION_YELLOW);
128 OutputString(" " + msg + "\n");
131 void Scheduler::FailWithErrorOnMainThread(const Err& err) {
132 err.PrintToStdout();
133 runner_.Quit();
136 void Scheduler::DoWork(const base::Closure& closure) {
137 closure.Run();
138 DecrementWorkCount();
141 void Scheduler::OnComplete() {
142 // Should be called on the main thread.
143 DCHECK(base::MessageLoop::current() == main_loop());
144 runner_.Quit();