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"
11 #include "tools/gn/switches.h"
13 Scheduler
* g_scheduler
= NULL
;
17 int GetThreadCount() {
18 std::string thread_count
=
19 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kThreads
);
22 if (thread_count
.empty() || !base::StringToInt(thread_count
, &result
))
29 Scheduler::Scheduler()
30 : pool_(new base::SequencedWorkerPool(GetThreadCount(), "worker_")),
31 input_file_manager_(new InputFileManager
),
32 verbose_logging_(false),
35 has_been_shutdown_(false) {
39 Scheduler::~Scheduler() {
40 if (!has_been_shutdown_
)
45 bool Scheduler::Run() {
49 base::AutoLock
lock(lock_
);
50 local_is_failed
= is_failed();
51 has_been_shutdown_
= true;
53 // Don't do this inside the lock since it will block on the workers, which
54 // may be in turn waiting on the lock.
56 return !local_is_failed
;
59 void Scheduler::Log(const std::string
& verb
, const std::string
& msg
) {
60 if (base::MessageLoop::current() == &main_loop_
) {
61 LogOnMainThread(verb
, msg
);
63 // The run loop always joins on the sub threads, so the lifetime of this
64 // object outlives the invocations of this function, hence "unretained".
65 main_loop_
.PostTask(FROM_HERE
,
66 base::Bind(&Scheduler::LogOnMainThread
,
67 base::Unretained(this), verb
, msg
));
71 void Scheduler::FailWithError(const Err
& err
) {
72 DCHECK(err
.has_error());
74 base::AutoLock
lock(lock_
);
76 if (is_failed_
|| has_been_shutdown_
)
77 return; // Ignore errors once we see one.
81 if (base::MessageLoop::current() == &main_loop_
) {
82 FailWithErrorOnMainThread(err
);
84 // The run loop always joins on the sub threads, so the lifetime of this
85 // object outlives the invocations of this function, hence "unretained".
86 main_loop_
.PostTask(FROM_HERE
,
87 base::Bind(&Scheduler::FailWithErrorOnMainThread
,
88 base::Unretained(this), err
));
92 void Scheduler::ScheduleWork(const base::Closure
& work
) {
94 pool_
->PostWorkerTaskWithShutdownBehavior(
95 FROM_HERE
, base::Bind(&Scheduler::DoWork
,
96 base::Unretained(this), work
),
97 base::SequencedWorkerPool::BLOCK_SHUTDOWN
);
100 void Scheduler::AddGenDependency(const base::FilePath
& file
) {
101 base::AutoLock
lock(lock_
);
102 gen_dependencies_
.push_back(file
);
105 std::vector
<base::FilePath
> Scheduler::GetGenDependencies() const {
106 base::AutoLock
lock(lock_
);
107 return gen_dependencies_
;
110 void Scheduler::IncrementWorkCount() {
111 base::AtomicRefCountInc(&work_count_
);
114 void Scheduler::DecrementWorkCount() {
115 if (!base::AtomicRefCountDec(&work_count_
)) {
116 if (base::MessageLoop::current() == &main_loop_
) {
119 main_loop_
.PostTask(FROM_HERE
,
120 base::Bind(&Scheduler::OnComplete
,
121 base::Unretained(this)));
126 void Scheduler::LogOnMainThread(const std::string
& verb
,
127 const std::string
& msg
) {
128 OutputString(verb
, DECORATION_YELLOW
);
129 OutputString(" " + msg
+ "\n");
132 void Scheduler::FailWithErrorOnMainThread(const Err
& err
) {
137 void Scheduler::DoWork(const base::Closure
& closure
) {
139 DecrementWorkCount();
142 void Scheduler::OnComplete() {
143 // Should be called on the main thread.
144 DCHECK(base::MessageLoop::current() == main_loop());