- add sources.
[platform/framework/web/crosswalk.git] / src / tools / gn / scheduler.cc
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 #include "tools/gn/scheduler.h"
6
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"
12
13 Scheduler* g_scheduler = NULL;
14
15 namespace {
16
17 int GetThreadCount() {
18   std::string thread_count =
19       CommandLine::ForCurrentProcess()->GetSwitchValueASCII("threads");
20
21   int result;
22   if (thread_count.empty() || !base::StringToInt(thread_count, &result))
23     return 32;
24   return result;
25 }
26
27 }  // namespace
28
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;
36 }
37
38 Scheduler::~Scheduler() {
39   g_scheduler = NULL;
40 }
41
42 bool Scheduler::Run() {
43   runner_.Run();
44   pool_->Shutdown();
45   return !is_failed();
46 }
47
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));
57   }
58 }
59
60 void Scheduler::FailWithError(const Err& err) {
61   DCHECK(err.has_error());
62   {
63     base::AutoLock lock(lock_);
64
65     if (is_failed_)
66       return;  // Ignore errors once we see one.
67     is_failed_ = true;
68   }
69
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));
78   }
79 }
80
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);
87 }
88
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);
94 }
95
96 void Scheduler::AddGenDependency(const base::FilePath& file) {
97   base::AutoLock lock(lock_);
98   gen_dependencies_.push_back(file);
99 }
100
101 std::vector<base::FilePath> Scheduler::GetGenDependencies() const {
102   base::AutoLock lock(lock_);
103   return gen_dependencies_;
104 }
105
106 void Scheduler::IncrementWorkCount() {
107   base::AtomicRefCountInc(&work_count_);
108 }
109
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)));
118     }
119   }
120 }
121
122 void Scheduler::LogOnMainThread(const std::string& verb,
123                                 const std::string& msg) {
124   OutputString(verb, DECORATION_YELLOW);
125   OutputString(" " + msg + "\n");
126 }
127
128 void Scheduler::FailWithErrorOnMainThread(const Err& err) {
129   err.PrintToStdout();
130   runner_.Quit();
131 }
132
133 void Scheduler::DoTargetFileWrite(const Target* target) {
134   NinjaTargetWriter::RunAndWriteFile(target);
135 }
136
137 void Scheduler::DoWork(const base::Closure& closure) {
138   closure.Run();
139   DecrementWorkCount();
140 }
141
142 void Scheduler::OnComplete() {
143   // Should be called on the main thread.
144   DCHECK(base::MessageLoop::current() == main_loop());
145   runner_.Quit();
146 }