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; return true;
auto compile_commands_path = default_build_path / "compile_commands.json"; 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; 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, default_build_path,
[&promise](int exit_status) { [&promise](int exit_status) {
promise.set_value(exit_status); promise.set_value(exit_status);
}); });
auto future = promise.get_future(); auto future = promise.get_future();
bool killed = false;
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) { while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) {
if(canceled && !killed) {
process->kill();
killed = true;
}
while(Gtk::Main::events_pending()) while(Gtk::Main::events_pending())
Gtk::Main::iteration(); 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)) if(!force && boost::filesystem::exists(debug_build_path / "CMakeCache.txt", ec))
return true; 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; 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, debug_build_path,
[&promise](int exit_status) { [&promise](int exit_status) {
promise.set_value(exit_status); promise.set_value(exit_status);
}); });
auto future = promise.get_future(); auto future = promise.get_future();
bool killed = false;
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) { while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) {
if(canceled && !killed) {
process->kill();
killed = true;
}
while(Gtk::Main::events_pending()) while(Gtk::Main::events_pending())
Gtk::Main::iteration(); 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) if(!force && compile_commands_exists)
return true; 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; 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, default_build_path,
[&promise](int exit_status) { [&promise](int exit_status) {
promise.set_value(exit_status); promise.set_value(exit_status);
}); });
auto future = promise.get_future(); auto future = promise.get_future();
bool killed = false;
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) { while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) {
if(canceled && !killed) {
process->kill();
killed = true;
}
while(Gtk::Main::events_pending()) while(Gtk::Main::events_pending())
Gtk::Main::iteration(); Gtk::Main::iteration();
} }
@ -94,15 +102,23 @@ bool Meson::update_debug_build(const boost::filesystem::path &debug_build_path,
if(!force && compile_commands_exists) if(!force && compile_commands_exists)
return true; 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; 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, debug_build_path,
[&promise](int exit_status) { [&promise](int exit_status) {
promise.set_value(exit_status); promise.set_value(exit_status);
}); });
auto future = promise.get_future(); auto future = promise.get_future();
bool killed = false;
while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) { while(future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) {
if(canceled && !killed) {
process->kill();
killed = true;
}
while(Gtk::Main::events_pending()) while(Gtk::Main::events_pending())
Gtk::Main::iteration(); 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(); 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::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) {
std::thread async_execute_thread([this, command, path, callback, quiet]() {
perform_scroll_to_bottom = true;
LockGuard lock(processes_mutex);
stdin_buffer.clear(); 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) { auto process = std::make_shared<TinyProcessLib::Process>(command, path.string(), [this, quiet](const char *bytes, size_t n) {
if(!quiet) { if(!quiet) {
// Print stdout message sequentially to avoid the GUI becoming unresponsive // 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(); message_printed.get_future().get();
} }
}, true); }, true);
auto pid = process->get_id(); auto pid = process->get_id();
if(pid <= 0) { if(pid <= 0) {
lock.unlock();
async_print("Error: failed to run command: " + command + "\n", true); async_print("Error: failed to run command: " + command + "\n", true);
if(callback) if(callback)
callback(-1); callback(-1);
return; return process;
} }
else { else {
LockGuard lock(processes_mutex);
processes.emplace_back(process); 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(); auto exit_status = process->get_exit_status();
{
lock.lock(); LockGuard lock(processes_mutex);
for(auto it = processes.begin(); it != processes.end(); it++) { for(auto it = processes.begin(); it != processes.end(); it++) {
if((*it)->get_id() == pid) { if((*it)->get_id() == pid) {
processes.erase(it); processes.erase(it);
break; break;
} }
} }
stdin_buffer.clear(); }
lock.unlock();
if(callback) if(callback)
callback(exit_status); callback(exit_status);
}); });
async_execute_thread.detach(); exit_status_thread.detach();
return process;
} }
void Terminal::kill_last_async_process(bool force) { void Terminal::kill_last_async_process(bool force) {
@ -410,10 +410,11 @@ void Terminal::print(std::string message, bool bold) {
if(!parent->is_visible()) if(!parent->is_visible())
parent->show(); parent->show();
bool expected = true; if(perform_scroll_to_bottom == true && scroll_to_bottom) {
if(perform_scroll_to_bottom.compare_exchange_strong(expected, false) && scroll_to_bottom) perform_scroll_to_bottom = false;
scroll_to_bottom(); scroll_to_bottom();
} }
}
Glib::ustring umessage = std::move(message); 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(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); 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_last_async_process(bool force = false);
void kill_async_processes(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); std::vector<std::shared_ptr<TinyProcessLib::Process>> processes GUARDED_BY(processes_mutex);
Glib::ustring stdin_buffer; Glib::ustring stdin_buffer;
std::atomic<bool> perform_scroll_to_bottom = {false}; bool perform_scroll_to_bottom = false;
}; };

Loading…
Cancel
Save