Add utility functions needed for rect-based event targeting
[chromium-blink-merge.git] / tools / gn / scheduler.cc
blob72c310bb071d1072698e3bdee6cf18b56c793965
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/ninja_target_writer.h"
11 #include "tools/gn/standard_out.h"
13 Scheduler* g_scheduler = NULL;
15 namespace {
17 int GetThreadCount() {
18 std::string thread_count =
19 CommandLine::ForCurrentProcess()->GetSwitchValueASCII("threads");
21 int result;
22 if (thread_count.empty() || !base::StringToInt(thread_count, &result))
23 return 32;
24 return result;
27 } // namespace
29 Scheduler::Scheduler()
30 : pool_(new base::SequencedWorkerPool(GetThreadCount(), "worker_")),
31 input_file_manager_(new InputFileManager),
32 verbose_logging_(false),
33 work_count_(0),
34 is_failed_(false) {
35 g_scheduler = this;
38 Scheduler::~Scheduler() {
39 g_scheduler = NULL;
42 bool Scheduler::Run() {
43 runner_.Run();
44 pool_->Shutdown();
45 return !is_failed();
48 void Scheduler::Log(const std::string& verb, const std::string& msg) {
49 if (base::MessageLoop::current() == &main_loop_) {
50 LogOnMainThread(verb, msg);
51 } else {
52 // The run loop always joins on the sub threads, so the lifetime of this
53 // object outlives the invocations of this function, hence "unretained".
54 main_loop_.PostTask(FROM_HERE,
55 base::Bind(&Scheduler::LogOnMainThread,
56 base::Unretained(this), verb, msg));
60 void Scheduler::FailWithError(const Err& err) {
61 DCHECK(err.has_error());
63 base::AutoLock lock(lock_);
65 if (is_failed_)
66 return; // Ignore errors once we see one.
67 is_failed_ = true;
70 if (base::MessageLoop::current() == &main_loop_) {
71 FailWithErrorOnMainThread(err);
72 } else {
73 // The run loop always joins on the sub threads, so the lifetime of this
74 // object outlives the invocations of this function, hence "unretained".
75 main_loop_.PostTask(FROM_HERE,
76 base::Bind(&Scheduler::FailWithErrorOnMainThread,
77 base::Unretained(this), err));
81 void Scheduler::ScheduleWork(const base::Closure& work) {
82 IncrementWorkCount();
83 pool_->PostWorkerTaskWithShutdownBehavior(
84 FROM_HERE, base::Bind(&Scheduler::DoWork,
85 base::Unretained(this), work),
86 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
89 void Scheduler::ScheduleTargetFileWrite(const Target* target) {
90 pool_->PostWorkerTaskWithShutdownBehavior(
91 FROM_HERE, base::Bind(&Scheduler::DoTargetFileWrite,
92 base::Unretained(this), target),
93 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
96 void Scheduler::AddGenDependency(const base::FilePath& file) {
97 base::AutoLock lock(lock_);
98 gen_dependencies_.push_back(file);
101 std::vector<base::FilePath> Scheduler::GetGenDependencies() const {
102 base::AutoLock lock(lock_);
103 return gen_dependencies_;
106 void Scheduler::IncrementWorkCount() {
107 base::AtomicRefCountInc(&work_count_);
110 void Scheduler::DecrementWorkCount() {
111 if (!base::AtomicRefCountDec(&work_count_)) {
112 if (base::MessageLoop::current() == &main_loop_) {
113 OnComplete();
114 } else {
115 main_loop_.PostTask(FROM_HERE,
116 base::Bind(&Scheduler::OnComplete,
117 base::Unretained(this)));
122 void Scheduler::LogOnMainThread(const std::string& verb,
123 const std::string& msg) {
124 OutputString(verb, DECORATION_YELLOW);
125 OutputString(" " + msg + "\n");
128 void Scheduler::FailWithErrorOnMainThread(const Err& err) {
129 err.PrintToStdout();
130 runner_.Quit();
133 void Scheduler::DoTargetFileWrite(const Target* target) {
134 NinjaTargetWriter::RunAndWriteFile(target);
137 void Scheduler::DoWork(const base::Closure& closure) {
138 closure.Run();
139 DecrementWorkCount();
142 void Scheduler::OnComplete() {
143 // Should be called on the main thread.
144 DCHECK(base::MessageLoop::current() == main_loop());
145 runner_.Quit();