Browse Source

Fixes #431: can now cancel creating/updating build folder

pipelines/235045657
eidheim 5 years ago
parent
commit
727d9c1c0c
  1. 24
      src/cmake.cpp
  2. 24
      src/meson.cpp
  3. 31
      src/terminal.cpp
  4. 4
      src/terminal.hpp

24
src/cmake.cpp

@ -60,15 +60,23 @@ bool CMake::update_default_build(const boost::filesystem::path &default_build_pa
return true;
auto compile_commands_path = default_build_path / "compile_commands.json";
Dialog::Message message("Creating/updating default build");
bool canceled = false;
Dialog::Message message("Creating/updating default build", [&canceled] {
canceled = true;
});
std::promise<int> promise;
Terminal::get().async_process(Config::get().project.cmake.command + ' ' + filesystem::escape_argument(project_path.string()) + " -DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
auto process = Terminal::get().async_process(Config::get().project.cmake.command + ' ' + filesystem::escape_argument(project_path.string()) + " -DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
default_build_path,
[&promise](int exit_status) {
promise.set_value(exit_status);
});
auto future = promise.get_future();
bool killed = false;
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) {
if(canceled && !killed) {
process->kill();
killed = true;
}
while(Gtk::Main::events_pending())
Gtk::Main::iteration();
}
@ -112,15 +120,23 @@ bool CMake::update_debug_build(const boost::filesystem::path &debug_build_path,
if(!force && boost::filesystem::exists(debug_build_path / "CMakeCache.txt", ec))
return true;
Dialog::Message message("Creating/updating debug build");
bool canceled = false;
Dialog::Message message("Creating/updating debug build", [&canceled] {
canceled = true;
});
std::promise<int> promise;
Terminal::get().async_process(Config::get().project.cmake.command + ' ' + filesystem::escape_argument(project_path.string()) + " -DCMAKE_BUILD_TYPE=Debug",
auto process = Terminal::get().async_process(Config::get().project.cmake.command + ' ' + filesystem::escape_argument(project_path.string()) + " -DCMAKE_BUILD_TYPE=Debug",
debug_build_path,
[&promise](int exit_status) {
promise.set_value(exit_status);
});
auto future = promise.get_future();
bool killed = false;
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) {
if(canceled && !killed) {
process->kill();
killed = true;
}
while(Gtk::Main::events_pending())
Gtk::Main::iteration();
}

24
src/meson.cpp

@ -60,15 +60,23 @@ bool Meson::update_default_build(const boost::filesystem::path &default_build_pa
if(!force && compile_commands_exists)
return true;
Dialog::Message message("Creating/updating default build");
bool canceled = false;
Dialog::Message message("Creating/updating default build", [&canceled] {
canceled = true;
});
std::promise<int> promise;
Terminal::get().async_process(Config::get().project.meson.command + ' ' + (compile_commands_exists ? "--internal regenerate " : "") + "--buildtype plain " + filesystem::escape_argument(project_path.string()),
auto process = Terminal::get().async_process(Config::get().project.meson.command + ' ' + (compile_commands_exists ? "--internal regenerate " : "") + "--buildtype plain " + filesystem::escape_argument(project_path.string()),
default_build_path,
[&promise](int exit_status) {
promise.set_value(exit_status);
});
auto future = promise.get_future();
bool killed = false;
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) {
if(canceled && !killed) {
process->kill();
killed = true;
}
while(Gtk::Main::events_pending())
Gtk::Main::iteration();
}
@ -94,15 +102,23 @@ bool Meson::update_debug_build(const boost::filesystem::path &debug_build_path,
if(!force && compile_commands_exists)
return true;
Dialog::Message message("Creating/updating debug build");
bool canceled = false;
Dialog::Message message("Creating/updating debug build", [&canceled] {
canceled = true;
});
std::promise<int> promise;
Terminal::get().async_process(Config::get().project.meson.command + ' ' + (compile_commands_exists ? "--internal regenerate " : "") + "--buildtype debug " + filesystem::escape_argument(project_path.string()),
auto process = Terminal::get().async_process(Config::get().project.meson.command + ' ' + (compile_commands_exists ? "--internal regenerate " : "") + "--buildtype debug " + filesystem::escape_argument(project_path.string()),
debug_build_path,
[&promise](int exit_status) {
promise.set_value(exit_status);
});
auto future = promise.get_future();
bool killed = false;
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) {
if(canceled && !killed) {
process->kill();
killed = true;
}
while(Gtk::Main::events_pending())
Gtk::Main::iteration();
}

31
src/terminal.cpp

@ -254,11 +254,10 @@ int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, c
return process.get_exit_status();
}
void Terminal::async_process(const std::string &command, const boost::filesystem::path &path, const std::function<void(int exit_status)> &callback, bool quiet) {
std::thread async_execute_thread([this, command, path, callback, quiet]() {
perform_scroll_to_bottom = true;
LockGuard lock(processes_mutex);
std::shared_ptr<TinyProcessLib::Process> Terminal::async_process(const std::string &command, const boost::filesystem::path &path, std::function<void(int exit_status)> callback, bool quiet) {
stdin_buffer.clear();
perform_scroll_to_bottom = true;
auto process = std::make_shared<TinyProcessLib::Process>(command, path.string(), [this, quiet](const char *bytes, size_t n) {
if(!quiet) {
// Print stdout message sequentially to avoid the GUI becoming unresponsive
@ -280,35 +279,36 @@ void Terminal::async_process(const std::string &command, const boost::filesystem
message_printed.get_future().get();
}
}, true);
auto pid = process->get_id();
if(pid <= 0) {
lock.unlock();
async_print("Error: failed to run command: " + command + "\n", true);
if(callback)
callback(-1);
return;
return process;
}
else {
LockGuard lock(processes_mutex);
processes.emplace_back(process);
lock.unlock();
}
std::thread exit_status_thread([this, process, pid, callback = std::move(callback)]() {
auto exit_status = process->get_exit_status();
lock.lock();
{
LockGuard lock(processes_mutex);
for(auto it = processes.begin(); it != processes.end(); it++) {
if((*it)->get_id() == pid) {
processes.erase(it);
break;
}
}
stdin_buffer.clear();
lock.unlock();
}
if(callback)
callback(exit_status);
});
async_execute_thread.detach();
exit_status_thread.detach();
return process;
}
void Terminal::kill_last_async_process(bool force) {
@ -410,10 +410,11 @@ void Terminal::print(std::string message, bool bold) {
if(!parent->is_visible())
parent->show();
bool expected = true;
if(perform_scroll_to_bottom.compare_exchange_strong(expected, false) && scroll_to_bottom)
if(perform_scroll_to_bottom == true && scroll_to_bottom) {
perform_scroll_to_bottom = false;
scroll_to_bottom();
}
}
Glib::ustring umessage = std::move(message);

4
src/terminal.hpp

@ -21,7 +21,7 @@ public:
int process(const std::string &command, const boost::filesystem::path &path = "", bool use_pipes = true);
int process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path = "", std::ostream *stderr_stream = nullptr);
void async_process(const std::string &command, const boost::filesystem::path &path = "", const std::function<void(int exit_status)> &callback = nullptr, bool quiet = false);
std::shared_ptr<TinyProcessLib::Process> async_process(const std::string &command, const boost::filesystem::path &path = "", std::function<void(int exit_status)> callback = nullptr, bool quiet = false);
void kill_last_async_process(bool force = false);
void kill_async_processes(bool force = false);
@ -61,5 +61,5 @@ private:
std::vector<std::shared_ptr<TinyProcessLib::Process>> processes GUARDED_BY(processes_mutex);
Glib::ustring stdin_buffer;
std::atomic<bool> perform_scroll_to_bottom = {false};
bool perform_scroll_to_bottom = false;
};

Loading…
Cancel
Save