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"
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
;
16 int GetThreadCount() {
17 std::string thread_count
=
18 CommandLine::ForCurrentProcess()->GetSwitchValueASCII("threads");
21 if (thread_count
.empty() || !base::StringToInt(thread_count
, &result
))
28 Scheduler::Scheduler()
29 : pool_(new base::SequencedWorkerPool(GetThreadCount(), "worker_")),
30 input_file_manager_(new InputFileManager
),
31 verbose_logging_(false),
34 has_been_shutdown_(false) {
38 Scheduler::~Scheduler() {
39 if (!has_been_shutdown_
)
44 bool Scheduler::Run() {
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.
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
);
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.
80 if (base::MessageLoop::current() == &main_loop_
) {
81 FailWithErrorOnMainThread(err
);
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
) {
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_
) {
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
) {
136 void Scheduler::DoWork(const base::Closure
& closure
) {
138 DecrementWorkCount();
141 void Scheduler::OnComplete() {
142 // Should be called on the main thread.
143 DCHECK(base::MessageLoop::current() == main_loop());