Browse Source

Fixed threaded dispatcher disconnects that must happen in the main thread. Also fixed potential crash when full reparse is needed before exiting juCi++

merge-requests/399/head
eidheim 6 years ago
parent
commit
a67becb7b8
  1. 91
      src/source_clang.cc
  2. 1
      src/source_clang.h
  3. 1
      src/source_diff.cc
  4. 1
      src/source_diff.h

91
src/source_clang.cc

@ -209,11 +209,14 @@ void Source::ClangViewParse::parse_initialize() {
void Source::ClangViewParse::soft_reparse(bool delayed) { void Source::ClangViewParse::soft_reparse(bool delayed) {
soft_reparse_needed = false; soft_reparse_needed = false;
parsed = false; parsed = false;
delayed_reparse_connection.disconnect();
if(parse_state != ParseState::PROCESSING) if(parse_state != ParseState::PROCESSING)
return; return;
parse_process_state = ParseProcessState::IDLE; parse_process_state = ParseProcessState::IDLE;
delayed_reparse_connection.disconnect();
delayed_reparse_connection = Glib::signal_timeout().connect([this]() { auto reparse = [this] {
parsed = false; parsed = false;
auto expected = ParseProcessState::IDLE; auto expected = ParseProcessState::IDLE;
if(parse_process_state.compare_exchange_strong(expected, ParseProcessState::STARTING)) { if(parse_process_state.compare_exchange_strong(expected, ParseProcessState::STARTING)) {
@ -222,7 +225,11 @@ void Source::ClangViewParse::soft_reparse(bool delayed) {
update_status_state(this); update_status_state(this);
} }
return false; return false;
}, delayed ? 1000 : 0); };
if(delayed)
delayed_reparse_connection = Glib::signal_timeout().connect(reparse, 1000);
else
reparse();
} }
const std::map<int, std::string> &Source::ClangViewParse::clang_types() { const std::map<int, std::string> &Source::ClangViewParse::clang_types() {
@ -1869,39 +1876,43 @@ Source::ClangView::ClangView(const boost::filesystem::path &file_path, const Gli
} }
void Source::ClangView::full_reparse() { void Source::ClangView::full_reparse() {
auto print_error = [this] { soft_reparse_needed = false;
Terminal::get().async_print("Error: failed to reparse " + file_path.string() + ". Please reopen the file manually.\n", true); parsed = false;
}; delayed_reparse_connection.disconnect();
full_reparse_needed = false; delayed_full_reparse_connection.disconnect();
if(parse_state != ParseState::PROCESSING)
return;
if(full_reparse_running) { if(full_reparse_running) {
print_error(); delayed_full_reparse_connection = Glib::signal_timeout().connect([this] {
full_reparse();
return false;
}, 100);
return; return;
} }
else {
auto expected = ParseState::PROCESSING; full_reparse_needed = false;
if(!parse_state.compare_exchange_strong(expected, ParseState::RESTARTING)) {
expected = ParseState::RESTARTING; parse_process_state = ParseProcessState::IDLE;
if(!parse_state.compare_exchange_strong(expected, ParseState::RESTARTING)) { autocomplete.state = Autocomplete::State::IDLE;
print_error(); auto expected = ParseState::PROCESSING;
return; if(!parse_state.compare_exchange_strong(expected, ParseState::RESTARTING))
} return;
}
autocomplete.state = Autocomplete::State::IDLE; full_reparse_running = true;
soft_reparse_needed = false; if(full_reparse_thread.joinable())
full_reparse_running = true; full_reparse_thread.join();
if(full_reparse_thread.joinable()) full_reparse_thread = std::thread([this]() {
full_reparse_thread.join(); if(parse_thread.joinable())
full_reparse_thread = std::thread([this]() { parse_thread.join();
if(parse_thread.joinable()) if(autocomplete.thread.joinable())
parse_thread.join(); autocomplete.thread.join();
if(autocomplete.thread.joinable()) dispatcher.post([this] {
autocomplete.thread.join(); parse_initialize();
dispatcher.post([this] { full_reparse_running = false;
parse_initialize();
full_reparse_running = false;
});
}); });
} });
} }
void Source::ClangView::async_delete() { void Source::ClangView::async_delete() {
@ -1919,21 +1930,17 @@ void Source::ClangView::async_delete() {
Usages::Clang::erase_unused_caches(project_paths_in_use); Usages::Clang::erase_unused_caches(project_paths_in_use);
Usages::Clang::cache_in_progress(); Usages::Clang::cache_in_progress();
if(!get_buffer()->get_modified()) { delayed_reparse_connection.disconnect();
if(full_reparse_needed) if(full_reparse_needed)
full_reparse(); full_reparse();
else if(soft_reparse_needed) else if(soft_reparse_needed || !parsed)
soft_reparse(); soft_reparse();
}
auto before_parse_time = std::time(nullptr); auto before_parse_time = std::time(nullptr);
delete_thread = std::thread([this, before_parse_time, project_paths_in_use = std::move(project_paths_in_use), buffer_modified = get_buffer()->get_modified()] { delete_thread = std::thread([this, before_parse_time, project_paths_in_use = std::move(project_paths_in_use), buffer_modified = get_buffer()->get_modified()] {
while(!parsed) while(!parsed && parse_state != ParseState::STOP)
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
delayed_reparse_connection.disconnect();
parse_state = ParseState::STOP; parse_state = ParseState::STOP;
dispatcher.disconnect();
if(buffer_modified) { if(buffer_modified) {
std::ifstream stream(file_path.string(), std::ios::binary); std::ifstream stream(file_path.string(), std::ios::binary);

1
src/source_clang.h

@ -32,6 +32,7 @@ namespace Source {
std::unique_ptr<clangmm::Tokens> clang_tokens; std::unique_ptr<clangmm::Tokens> clang_tokens;
std::vector<std::pair<clangmm::Offset, clangmm::Offset>> clang_tokens_offsets; std::vector<std::pair<clangmm::Offset, clangmm::Offset>> clang_tokens_offsets;
sigc::connection delayed_reparse_connection; sigc::connection delayed_reparse_connection;
sigc::connection delayed_full_reparse_connection;
void show_type_tooltips(const Gdk::Rectangle &rectangle) override; void show_type_tooltips(const Gdk::Rectangle &rectangle) override;

1
src/source_diff.cc

@ -48,7 +48,6 @@ Source::DiffView::DiffView(const boost::filesystem::path &file_path, const Glib:
} }
Source::DiffView::~DiffView() { Source::DiffView::~DiffView() {
dispatcher.disconnect();
if(repository) { if(repository) {
get_gutter(Gtk::TextWindowType::TEXT_WINDOW_LEFT)->remove(renderer.get()); get_gutter(Gtk::TextWindowType::TEXT_WINDOW_LEFT)->remove(renderer.get());
buffer_insert_connection.disconnect(); buffer_insert_connection.disconnect();

1
src/source_diff.h

@ -48,7 +48,6 @@ namespace Source {
std::unique_ptr<Renderer> renderer; std::unique_ptr<Renderer> renderer;
Dispatcher dispatcher; Dispatcher dispatcher;
Mutex parse_mutex; Mutex parse_mutex;
std::shared_ptr<Git::Repository> repository; std::shared_ptr<Git::Repository> repository;

Loading…
Cancel
Save