Browse Source

Reverted last commit, and instead made tiny-process-library handlers wait until GUI thread has printed the message

pipelines/235045657
eidheim 5 years ago
parent
commit
c1bb207828
  1. 72
      src/terminal.cpp
  2. 12
      src/terminal.hpp

72
src/terminal.cpp

@ -24,44 +24,6 @@ Terminal::Terminal() : Source::SearchView() {
link_mouse_cursor = Gdk::Cursor::create(Gdk::CursorType::HAND1);
default_mouse_cursor = Gdk::Cursor::create(Gdk::CursorType::XTERM);
message_queue_thread = std::thread([this] {
while(true) {
std::unique_lock<std::mutex> lock(message_queue_mutex);
while(message_queue.empty() && !message_queue_stop)
message_queue_condition_variable.wait(lock);
if(message_queue_stop)
break;
// Combine messages to avoid overloading GUI thread
for(auto it = message_queue.begin(); it != message_queue.end();) {
auto next = std::next(it);
if(next == message_queue.end())
break;
if(it->second == next->second) {
it->first += next->first;
message_queue.erase(next);
}
else
++it;
}
std::promise<void> messages_printed;
dispatcher.post([message_queue = std::move(message_queue), &messages_printed]() mutable {
while(!message_queue.empty()) {
Terminal::get().print(std::move(message_queue.begin()->first), message_queue.begin()->second);
message_queue.pop_front();
}
messages_printed.set_value();
});
message_queue.clear();
// Wait until messages have been printed
lock.unlock();
messages_printed.get_future().get();
}
});
// Apply link tags
get_buffer()->signal_insert().connect([this](const Gtk::TextIter &iter, const Glib::ustring &text, int /*bytes*/) {
std::string line_start;
@ -114,23 +76,14 @@ Terminal::Terminal() : Source::SearchView() {
});
}
Terminal::~Terminal() {
{
std::unique_lock<std::mutex> lock(message_queue_mutex);
message_queue_stop = true;
}
message_queue_condition_variable.notify_one();
message_queue_thread.join();
}
int Terminal::process(const std::string &command, const boost::filesystem::path &path, bool use_pipes) {
perform_scroll_to_bottom = true;
std::unique_ptr<TinyProcessLib::Process> process;
if(use_pipes)
process = std::make_unique<TinyProcessLib::Process>(command, path.string(), [this](const char *bytes, size_t n) {
async_print(std::string(bytes, n));
sync_print(std::string(bytes, n));
}, [this](const char *bytes, size_t n) {
async_print(std::string(bytes, n), true);
sync_print(std::string(bytes, n), true);
});
else
process = std::make_unique<TinyProcessLib::Process>(command, path.string());
@ -158,7 +111,7 @@ int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, c
if(stderr_stream)
stderr_stream->write(bytes, n);
else
async_print(std::string(bytes, n), true);
sync_print(std::string(bytes, n), true);
}, true);
if(process.get_id() <= 0) {
@ -188,10 +141,10 @@ void Terminal::async_process(const std::string &command, const boost::filesystem
stdin_buffer.clear();
auto process = std::make_shared<TinyProcessLib::Process>(command, path.string(), [this, quiet](const char *bytes, size_t n) {
if(!quiet)
async_print(std::string(bytes, n));
sync_print(std::string(bytes, n));
}, [this, quiet](const char *bytes, size_t n) {
if(!quiet)
async_print(std::string(bytes, n), true);
sync_print(std::string(bytes, n), true);
}, true);
auto pid = process->get_id();
if(pid <= 0) {
@ -370,11 +323,18 @@ void Terminal::print(std::string message, bool bold) {
}
void Terminal::async_print(std::string message, bool bold) {
{
std::unique_lock<std::mutex> lock(message_queue_mutex);
message_queue.emplace_back(std::move(message), bold);
dispatcher.post([message = std::move(message), bold]() mutable {
Terminal::get().print(std::move(message), bold);
});
}
message_queue_condition_variable.notify_one();
void Terminal::sync_print(std::string message, bool bold) {
std::promise<void> done;
dispatcher.post([message = std::move(message), bold, &done]() mutable {
Terminal::get().print(std::move(message), bold);
done.set_value();
});
done.get_future().get();
}
void Terminal::configure() {

12
src/terminal.hpp

@ -5,7 +5,6 @@
#include "source_base.hpp"
#include <boost/filesystem.hpp>
#include <boost/optional.hpp>
#include <condition_variable>
#include <functional>
#include <gtkmm.h>
#include <iostream>
@ -20,15 +19,15 @@ public:
return singleton;
}
~Terminal() override;
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);
void kill_last_async_process(bool force = false);
void kill_async_processes(bool force = false);
/// Must be called from main thread
void print(std::string message, bool bold = false);
/// Callable from any thread.
void async_print(std::string message, bool bold = false);
void configure();
@ -50,11 +49,8 @@ private:
Glib::RefPtr<Gdk::Cursor> default_mouse_cursor;
size_t deleted_lines = 0;
std::thread message_queue_thread;
bool message_queue_stop = false;
std::condition_variable message_queue_condition_variable;
std::mutex message_queue_mutex;
std::list<std::pair<std::string, bool>> message_queue;
/// Made for tiny-process-library handlers: prints in GUI thread, and waits until the message has been printed. Callable from any thread.
void sync_print(std::string message, bool bold = false);
struct Link {
int start_pos, end_pos;

Loading…
Cancel
Save