Ninja
real_command_runner.cc
Go to the documentation of this file.
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "build.h"
16 #include "jobserver.h"
17 #include "limits.h"
18 #include "subprocess.h"
19 
21  explicit RealCommandRunner(const BuildConfig& config,
22  Jobserver::Client* jobserver)
23  : config_(config), jobserver_(jobserver) {}
24  size_t CanRunMore() const override;
25  bool StartCommand(Edge* edge) override;
26  bool WaitForCommand(Result* result) override;
27  std::vector<Edge*> GetActiveEdges() override;
28  void Abort() override;
29 
30  void ClearJobTokens() {
31  if (jobserver_) {
32  for (Edge* edge : GetActiveEdges()) {
33  jobserver_->Release(std::move(edge->job_slot_));
34  }
35  }
36  }
37 
41  std::map<const Subprocess*, Edge*> subproc_to_edge_;
42 };
43 
44 std::vector<Edge*> RealCommandRunner::GetActiveEdges() {
45  std::vector<Edge*> edges;
46  for (std::map<const Subprocess*, Edge*>::iterator e =
47  subproc_to_edge_.begin();
48  e != subproc_to_edge_.end(); ++e)
49  edges.push_back(e->second);
50  return edges;
51 }
52 
55  subprocs_.Clear();
56 }
57 
59  size_t subproc_number =
60  subprocs_.running_.size() + subprocs_.finished_.size();
61 
62  int64_t capacity = config_.parallelism - subproc_number;
63 
64  if (jobserver_) {
65  // When a jobserver token pool is used, make the
66  // capacity infinite, and let FindWork() limit jobs
67  // through token acquisitions instead.
68  capacity = INT_MAX;
69  }
70 
71  if (config_.max_load_average > 0.0f) {
72  int load_capacity = config_.max_load_average - GetLoadAverage();
73  if (load_capacity < capacity)
74  capacity = load_capacity;
75  }
76 
77  if (capacity < 0)
78  capacity = 0;
79 
80  if (capacity == 0 && subprocs_.running_.empty())
81  // Ensure that we make progress.
82  capacity = 1;
83 
84  return capacity;
85 }
86 
88  std::string command = edge->EvaluateCommand();
89  Subprocess* subproc = subprocs_.Add(command, edge->use_console());
90  if (!subproc)
91  return false;
92  subproc_to_edge_.insert(std::make_pair(subproc, edge));
93 
94  return true;
95 }
96 
98  Subprocess* subproc;
99  while ((subproc = subprocs_.NextFinished()) == NULL) {
100  bool interrupted = subprocs_.DoWork();
101  if (interrupted)
102  return false;
103  }
104 
105  result->status = subproc->Finish();
106  result->output = subproc->GetOutput();
107 
108  std::map<const Subprocess*, Edge*>::iterator e =
109  subproc_to_edge_.find(subproc);
110  result->edge = e->second;
111  subproc_to_edge_.erase(e);
112 
113  delete subproc;
114  return true;
115 }
116 
118  Jobserver::Client* jobserver) {
119  return new RealCommandRunner(config, jobserver);
120 }
A Jobserver::Client instance models a client of an external GNU jobserver pool, which can be implemen...
Definition: jobserver.h:189
virtual void Release(Slot slot)
Release a slot to the pool.
Definition: jobserver.h:208
Options (e.g. verbosity, parallelism) passed to a build.
Definition: build.h:176
double max_load_average
The maximum load average we must not exceed.
Definition: build.h:192
int parallelism
Definition: build.h:187
The result of waiting for a command.
Definition: build.h:156
ExitStatus status
Definition: build.h:159
std::string output
Definition: build.h:160
CommandRunner is an interface that wraps running the build subcommands.
Definition: build.h:150
static CommandRunner * factory(const BuildConfig &config, Jobserver::Client *jobserver)
Creates the RealCommandRunner.
An edge in the dependency graph; links between Nodes using Rules.
Definition: graph.h:175
std::string EvaluateCommand(bool incl_rsp_file=false) const
Expand all variables in a command and return it as a string.
Definition: graph.cc:501
bool use_console() const
Definition: graph.cc:567
std::vector< Edge * > GetActiveEdges() override
Jobserver::Client * jobserver_
bool WaitForCommand(Result *result) override
Wait for a command to complete, or return false if interrupted.
bool StartCommand(Edge *edge) override
RealCommandRunner(const BuildConfig &config, Jobserver::Client *jobserver)
void Abort() override
size_t CanRunMore() const override
const BuildConfig & config_
std::map< const Subprocess *, Edge * > subproc_to_edge_
SubprocessSet runs a ppoll/pselect() loop around a set of Subprocesses.
Definition: subprocess.h:101
std::queue< Subprocess * > finished_
Definition: subprocess.h:111
Subprocess * NextFinished()
std::vector< Subprocess * > running_
Definition: subprocess.h:110
Subprocess * Add(const std::string &command, bool use_console=false)
Subprocess wraps a single async subprocess.
Definition: subprocess.h:42
ExitStatus Finish()
Returns ExitSuccess on successful process exit, ExitInterrupted if the process was interrupted,...
const std::string & GetOutput() const
double GetLoadAverage()
Definition: util.cc:981
signed long long int64_t
A 64-bit integer type.
Definition: win32port.h:28