Skip to content

Commit

Permalink
Move RealCommandRunner into its own file
Browse files Browse the repository at this point in the history
  • Loading branch information
jhasse committed Nov 7, 2024
1 parent 089af00 commit 27c78a3
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 77 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ add_library(libninja OBJECT
src/metrics.cc
src/missing_deps.cc
src/parser.cc
src/real_command_runner.cc
src/state.cc
src/status_printer.cc
src/string_piece_util.cc
Expand Down
1 change: 1 addition & 0 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ def has_re2c() -> bool:
'metrics',
'missing_deps',
'parser',
'real_command_runner',
'state',
'status_printer',
'string_piece_util',
Expand Down
78 changes: 1 addition & 77 deletions src/build.cc
Original file line number Diff line number Diff line change
Expand Up @@ -591,82 +591,6 @@ void Plan::Dump() const {
printf("ready: %d\n", (int)ready_.size());
}

struct RealCommandRunner : public CommandRunner {
explicit RealCommandRunner(const BuildConfig& config) : config_(config) {}
size_t CanRunMore() const override;
bool StartCommand(Edge* edge) override;
bool WaitForCommand(Result* result) override;
vector<Edge*> GetActiveEdges() override;
void Abort() override;

const BuildConfig& config_;
SubprocessSet subprocs_;
map<const Subprocess*, Edge*> subproc_to_edge_;
};

vector<Edge*> RealCommandRunner::GetActiveEdges() {
vector<Edge*> edges;
for (map<const Subprocess*, Edge*>::iterator e = subproc_to_edge_.begin();
e != subproc_to_edge_.end(); ++e)
edges.push_back(e->second);
return edges;
}

void RealCommandRunner::Abort() {
subprocs_.Clear();
}

size_t RealCommandRunner::CanRunMore() const {
size_t subproc_number =
subprocs_.running_.size() + subprocs_.finished_.size();

int64_t capacity = config_.parallelism - subproc_number;

if (config_.max_load_average > 0.0f) {
int load_capacity = config_.max_load_average - GetLoadAverage();
if (load_capacity < capacity)
capacity = load_capacity;
}

if (capacity < 0)
capacity = 0;

if (capacity == 0 && subprocs_.running_.empty())
// Ensure that we make progress.
capacity = 1;

return capacity;
}

bool RealCommandRunner::StartCommand(Edge* edge) {
string command = edge->EvaluateCommand();
Subprocess* subproc = subprocs_.Add(command, edge->use_console());
if (!subproc)
return false;
subproc_to_edge_.insert(make_pair(subproc, edge));

return true;
}

bool RealCommandRunner::WaitForCommand(Result* result) {
Subprocess* subproc;
while ((subproc = subprocs_.NextFinished()) == NULL) {
bool interrupted = subprocs_.DoWork();
if (interrupted)
return false;
}

result->status = subproc->Finish();
result->output = subproc->GetOutput();

map<const Subprocess*, Edge*>::iterator e = subproc_to_edge_.find(subproc);
result->edge = e->second;
subproc_to_edge_.erase(e);

delete subproc;
return true;
}

Builder::Builder(State* state, const BuildConfig& config, BuildLog* build_log,
DepsLog* deps_log, DiskInterface* disk_interface,
Status* status, int64_t start_time_millis)
Expand Down Expand Up @@ -775,7 +699,7 @@ bool Builder::Build(string* err) {
if (config_.dry_run)
command_runner_.reset(new DryRunCommandRunner);
else
command_runner_.reset(new RealCommandRunner(config_));
command_runner_.reset(CommandRunner::factory(config_));
}

// We are about to start the build process.
Expand Down
5 changes: 5 additions & 0 deletions src/build.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ struct Plan {
int wanted_edges_;
};

struct BuildConfig;

/// CommandRunner is an interface that wraps running the build
/// subcommands. This allows tests to abstract out running commands.
/// RealCommandRunner is an implementation that actually runs commands.
Expand All @@ -162,6 +164,9 @@ struct CommandRunner {

virtual std::vector<Edge*> GetActiveEdges() { return std::vector<Edge*>(); }
virtual void Abort() {}

/// Creates the RealCommandRunner
static CommandRunner* factory(const BuildConfig& config);
};

/// Options (e.g. verbosity, parallelism) passed to a build.
Expand Down
98 changes: 98 additions & 0 deletions src/real_command_runner.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "build.h"
#include "subprocess.h"

struct RealCommandRunner : public CommandRunner {
explicit RealCommandRunner(const BuildConfig& config) : config_(config) {}
size_t CanRunMore() const override;
bool StartCommand(Edge* edge) override;
bool WaitForCommand(Result* result) override;
std::vector<Edge*> GetActiveEdges() override;
void Abort() override;

const BuildConfig& config_;
SubprocessSet subprocs_;
std::map<const Subprocess*, Edge*> subproc_to_edge_;
};

std::vector<Edge*> RealCommandRunner::GetActiveEdges() {
std::vector<Edge*> edges;
for (std::map<const Subprocess*, Edge*>::iterator e =
subproc_to_edge_.begin();
e != subproc_to_edge_.end(); ++e)
edges.push_back(e->second);
return edges;
}

void RealCommandRunner::Abort() {
subprocs_.Clear();
}

size_t RealCommandRunner::CanRunMore() const {
size_t subproc_number =
subprocs_.running_.size() + subprocs_.finished_.size();

int64_t capacity = config_.parallelism - subproc_number;

if (config_.max_load_average > 0.0f) {
int load_capacity = config_.max_load_average - GetLoadAverage();
if (load_capacity < capacity)
capacity = load_capacity;
}

if (capacity < 0)
capacity = 0;

if (capacity == 0 && subprocs_.running_.empty())
// Ensure that we make progress.
capacity = 1;

return capacity;
}

bool RealCommandRunner::StartCommand(Edge* edge) {
std::string command = edge->EvaluateCommand();
Subprocess* subproc = subprocs_.Add(command, edge->use_console());
if (!subproc)
return false;
subproc_to_edge_.insert(std::make_pair(subproc, edge));

return true;
}

bool RealCommandRunner::WaitForCommand(Result* result) {
Subprocess* subproc;
while ((subproc = subprocs_.NextFinished()) == NULL) {
bool interrupted = subprocs_.DoWork();
if (interrupted)
return false;
}

result->status = subproc->Finish();
result->output = subproc->GetOutput();

std::map<const Subprocess*, Edge*>::iterator e =
subproc_to_edge_.find(subproc);
result->edge = e->second;
subproc_to_edge_.erase(e);

delete subproc;
return true;
}

CommandRunner* CommandRunner::factory(const BuildConfig& config) {
return new RealCommandRunner(config);
}

0 comments on commit 27c78a3

Please sign in to comment.