From 1d581df887d4a7b05431c3c966e425020d731049 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sat, 1 Aug 2015 23:04:26 +0200 Subject: [PATCH] Users should now experience no delay in Juci, even when closing tabs that are processing or when quitting the application while source files are processed. That is, resources are now freed from a seperate thread. --- src/notebook.cc | 10 +++++++++- src/notebook.h | 2 +- src/source.cc | 37 ++++++++++++++++++++++++------------- src/source.h | 16 ++++++++++------ 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/notebook.cc b/src/notebook.cc index 24ad15e..b3d183f 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -19,7 +19,7 @@ int Notebook::size() { Source::View* Notebook::get_view(int page) { if(page>=size()) return nullptr; - return source_views.at(page).get(); + return source_views.at(page); } Source::View* Notebook::get_current_view() { @@ -125,9 +125,17 @@ bool Notebook::close_current_page() { } int page = get_current_page(); remove_page(page); + if(get_current_page()==-1) + Singleton::status()->set_text(""); + auto source_view=source_views.at(page); source_views.erase(source_views.begin()+ page); scrolled_windows.erase(scrolled_windows.begin()+page); hboxes.erase(hboxes.begin()+page); + if(auto source_clang_view=dynamic_cast(source_view)) { + source_clang_view->delete_object(); + } + else + delete source_view; } return true; } diff --git a/src/notebook.h b/src/notebook.h index 79fb9f9..be21b0b 100644 --- a/src/notebook.h +++ b/src/notebook.h @@ -23,7 +23,7 @@ public: private: bool save_modified_dialog(); - std::vector > source_views; + std::vector source_views; //Is NOT freed in destructor, this is intended for quick program exit. std::vector > scrolled_windows; std::vector > hboxes; }; diff --git a/src/source.cc b/src/source.cc index fe7f71c..d27e381 100644 --- a/src/source.cc +++ b/src/source.cc @@ -390,16 +390,6 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangViewParse::on_mark_set), false); } -Source::ClangViewParse::~ClangViewParse() { - //TODO: Is it possible to stop the clang-process in progress? - parsing_in_progress->cancel("canceled"); - parse_thread_stop=true; - if(parse_thread.joinable()) - parse_thread.join(); - parsing_mutex.lock(); //Be sure not to destroy while still parsing with libclang - parsing_mutex.unlock(); -} - void Source::ClangViewParse:: init_syntax_highlighting(const std::map &buffers, @@ -872,14 +862,14 @@ void Source::ClangViewAutocomplete::autocomplete() { } buffer+="\n"; set_status("autocomplete..."); - std::thread autocomplete_thread([this, ac_data, line_nr, column_nr, buffer_map](){ + if(autocomplete_thread.joinable()) + autocomplete_thread.join(); + autocomplete_thread=std::thread([this, ac_data, line_nr, column_nr, buffer_map](){ parsing_mutex.lock(); *ac_data=move(get_autocomplete_suggestions(line_nr, column_nr, *buffer_map)); autocomplete_done(); parsing_mutex.unlock(); }); - - autocomplete_thread.detach(); } } @@ -1051,3 +1041,24 @@ Source::ClangViewAutocomplete(file_path, project_path) { } }; } + +Source::ClangView::ClangView(const std::string& file_path, const std::string& project_path): ClangViewRefactor(file_path, project_path) { + do_delete_object.connect([this](){ + if(delete_thread.joinable()) + delete_thread.join(); + delete this; + }); +} + +void Source::ClangView::delete_object() { + parsing_in_progress->cancel("canceled, freeing resources in the background"); + parse_thread_stop=true; + delete_thread=std::thread([this](){ + //TODO: Is it possible to stop the clang-process in progress? + if(parse_thread.joinable()) + parse_thread.join(); + if(autocomplete_thread.joinable()) + autocomplete_thread.join(); + do_delete_object(); + }); +} \ No newline at end of file diff --git a/src/source.h b/src/source.h index c874520..83f4e24 100644 --- a/src/source.h +++ b/src/source.h @@ -90,7 +90,6 @@ namespace Source { class ClangViewParse : public View { public: ClangViewParse(const std::string& file_path, const std::string& project_path); - ~ClangViewParse(); protected: void start_reparse(); bool on_key_press_event(GdkEventKey* key); @@ -101,6 +100,10 @@ namespace Source { bool clang_readable=false; sigc::connection delayed_reparse_connection; sigc::connection delayed_tooltips_connection; + + std::shared_ptr parsing_in_progress; + std::thread parse_thread; + std::atomic parse_thread_stop; private: std::map get_buffer_map() const; // inits the syntax highligthing on file open @@ -122,15 +125,12 @@ namespace Source { static clang::Index clang_index; std::vector get_compilation_commands(); - std::shared_ptr parsing_in_progress; Glib::Dispatcher parse_done; Glib::Dispatcher parse_start; - std::thread parse_thread; std::map parse_thread_buffer_map; std::mutex parse_thread_buffer_map_mutex; std::atomic parse_thread_go; std::atomic parse_thread_mapped; - std::atomic parse_thread_stop; }; class ClangViewAutocomplete : public ClangViewParse { @@ -139,6 +139,7 @@ namespace Source { protected: bool on_key_press_event(GdkEventKey* key); bool on_focus_out_event(GdkEventFocus* event); + std::thread autocomplete_thread; private: void start_autocomplete(); void autocomplete(); @@ -166,8 +167,11 @@ namespace Source { class ClangView : public ClangViewRefactor { public: - ClangView(const std::string& file_path, const std::string& project_path): - ClangViewRefactor(file_path, project_path) {} + ClangView(const std::string& file_path, const std::string& project_path); + void delete_object(); + private: + Glib::Dispatcher do_delete_object; + std::thread delete_thread; }; }; // class Source #endif // JUCI_SOURCE_H_