From 2204b7cf0667cc1124606c9882aba82dcf650fc3 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Tue, 12 Aug 2014 19:24:09 +0100 Subject: [PATCH] Defer deletion of buffers to after the event loop We can have SelectionList in flights on the buffer, so mark it for deletion by moving it in a buffer trash, and effectively delete it later, at a point where there should not be any further access to it. --- src/buffer_manager.cc | 18 +++++++++++++++++- src/buffer_manager.hh | 2 ++ src/client.hh | 3 +++ src/client_manager.cc | 6 ++++++ src/client_manager.hh | 1 + src/event_manager.cc | 4 ---- src/main.cc | 5 +++++ 7 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/buffer_manager.cc b/src/buffer_manager.cc index bb03ef6d..a521ad58 100644 --- a/src/buffer_manager.cc +++ b/src/buffer_manager.cc @@ -41,6 +41,14 @@ void BufferManager::unregister_buffer(Buffer& buffer) return; } } + for (auto it = m_buffer_trash.begin(); it != m_buffer_trash.end(); ++it) + { + if (*it == &buffer) + { + m_buffer_trash.erase(it); + return; + } + } kak_assert(false); } @@ -52,7 +60,9 @@ void BufferManager::delete_buffer(Buffer& buffer) { if (ClientManager::has_instance()) ClientManager::instance().ensure_no_client_uses_buffer(buffer); - delete it->get(); + + m_buffers.erase(it); + m_buffer_trash.emplace_back(&buffer); return; } } @@ -121,4 +131,10 @@ CandidateList BufferManager::complete_buffer_name(StringView prefix, return result.empty() ? subsequence_result : result; } +void BufferManager::clear_buffer_trash() +{ + while (not m_buffer_trash.empty()) + delete m_buffer_trash.back().get(); +} + } diff --git a/src/buffer_manager.hh b/src/buffer_manager.hh index cd7029ea..474833c4 100644 --- a/src/buffer_manager.hh +++ b/src/buffer_manager.hh @@ -37,8 +37,10 @@ public: CandidateList complete_buffer_name(StringView prefix, ByteCount cursor_pos = -1); + void clear_buffer_trash(); private: BufferList m_buffers; + BufferList m_buffer_trash; }; } diff --git a/src/client.hh b/src/client.hh index 66472808..a7f2d1ed 100644 --- a/src/client.hh +++ b/src/client.hh @@ -39,6 +39,9 @@ public: Context& context() { return m_input_handler.context(); } const Context& context() const { return m_input_handler.context(); } + InputHandler& input_handler() { return m_input_handler; } + const InputHandler& input_handler() const { return m_input_handler; } + void change_buffer(Buffer& buffer); const String& get_env_var(const String& name) const; diff --git a/src/client_manager.cc b/src/client_manager.cc index ac9c8452..3c1fb086 100644 --- a/src/client_manager.cc +++ b/src/client_manager.cc @@ -170,6 +170,12 @@ void ClientManager::redraw_clients() const client->redraw_ifn(); } +void ClientManager::clear_mode_trashes() const +{ + for (auto& client : m_clients) + client->input_handler().clear_mode_trash(); +} + CandidateList ClientManager::complete_client_name(StringView prefix, ByteCount cursor_pos) const { diff --git a/src/client_manager.hh b/src/client_manager.hh index 410adab5..e4d6da43 100644 --- a/src/client_manager.hh +++ b/src/client_manager.hh @@ -34,6 +34,7 @@ public: void add_free_window(std::unique_ptr&& window, SelectionList selections); void redraw_clients() const; + void clear_mode_trashes() const; Client* get_client_ifp(const String& name); Client& get_client(const String& name); diff --git a/src/event_manager.cc b/src/event_manager.cc index f670ada5..9a51b885 100644 --- a/src/event_manager.cc +++ b/src/event_manager.cc @@ -1,5 +1,4 @@ #include "event_manager.hh" -#include "client_manager.hh" #include @@ -82,9 +81,6 @@ void EventManager::handle_next_events() if (timer->next_date() <= now) timer->run(); } - - if (ClientManager::has_instance()) - ClientManager::instance().redraw_clients(); } void EventManager::force_signal(int fd) diff --git a/src/main.cc b/src/main.cc index 4fe582ba..117cc95c 100644 --- a/src/main.cc +++ b/src/main.cc @@ -421,7 +421,12 @@ int kakoune(const ParametersParser& parser) create_local_client(init_command); while (not terminate and (not client_manager.empty() or daemon)) + { event_manager.handle_next_events(); + client_manager.clear_mode_trashes(); + buffer_manager.clear_buffer_trash(); + client_manager.redraw_clients(); + } { Context empty_context;