From 530ecf212eedce7ae62c185873ae42033eeee925 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sun, 10 Jul 2016 16:01:33 +0100 Subject: [PATCH] Ensure buffer create/close hooks are run at appropriate times They used to be ran before the buffer was added to the buffer list we now run them afterwards. --- src/buffer.cc | 35 +++++++++++++++++++++++++---------- src/buffer.hh | 4 ++++ src/buffer_manager.cc | 15 ++++++++++++--- src/main.cc | 8 ++++---- 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/buffer.cc b/src/buffer.cc index 089103b1..df9a7613 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -69,8 +69,6 @@ Buffer::Buffer(String name, Flags flags, StringView data, m_last_save_undo_index(0), m_fs_timestamp(fs_timestamp) { - options().register_watcher(*this); - ParsedLines parsed_lines = parse_lines(data); if (parsed_lines.lines.empty()) @@ -87,9 +85,24 @@ Buffer::Buffer(String name, Flags flags, StringView data, apply_options(options(), parsed_lines); - if (flags & Flags::File) + // now we may begin to record undo data + if (not (flags & Flags::NoUndo)) + m_flags &= ~Flags::NoUndo; +} + +void Buffer::on_registered() +{ + // Ignore debug buffer, as it can be created in many + // corner cases (including while destroying the BufferManager + // if a BufClose hooks triggers writing to it. + if (m_flags & Flags::Debug) + return; + + options().register_watcher(*this); + + if (m_flags & Flags::File) { - if (flags & Flags::New) + if (m_flags & Buffer::Flags::New) run_hook_in_own_context("BufNew", m_name); else { @@ -100,19 +113,21 @@ Buffer::Buffer(String name, Flags flags, StringView data, run_hook_in_own_context("BufCreate", m_name); - // now we may begin to record undo data - if (not (flags & Flags::NoUndo)) - m_flags &= ~Flags::NoUndo; - for (auto& option : options().flatten_options()) on_option_changed(*option); } -Buffer::~Buffer() +void Buffer::on_unregistered() { - run_hook_in_own_context("BufClose", m_name); + if (m_flags & Flags::Debug) + return; options().unregister_watcher(*this); + run_hook_in_own_context("BufClose", m_name); +} + +Buffer::~Buffer() +{ m_values.clear(); } diff --git a/src/buffer.hh b/src/buffer.hh index 2b118c89..21f960f2 100644 --- a/src/buffer.hh +++ b/src/buffer.hh @@ -200,6 +200,10 @@ public: ConstArrayView changes_since(size_t timestamp) const; String debug_description() const; + + // Methods called by the buffer manager + void on_registered(); + void on_unregistered(); private: void on_option_changed(const Option& option) override; diff --git a/src/buffer_manager.cc b/src/buffer_manager.cc index e743bff0..98dfc7f1 100644 --- a/src/buffer_manager.cc +++ b/src/buffer_manager.cc @@ -22,6 +22,9 @@ BufferManager::~BufferManager() // hook while clearing m_buffers m_buffer_trash = std::move(m_buffers); + for (auto& buffer : m_buffer_trash) + buffer->on_unregistered(); + // Make sure not clients exists ClientManager::instance().clear(); } @@ -37,9 +40,12 @@ Buffer* BufferManager::create_buffer(String name, Buffer::Flags flags, throw name_not_unique(); } - m_buffers.emplace(m_buffers.begin(), new Buffer{std::move(name), flags, - data, fs_timestamp}); - return m_buffers.front().get(); + m_buffers.emplace(m_buffers.begin(), + new Buffer{std::move(name), flags, data, fs_timestamp}); + auto& buffer = *m_buffers.front(); + buffer.on_registered(); + + return &buffer; } void BufferManager::delete_buffer(Buffer& buffer) @@ -48,10 +54,13 @@ void BufferManager::delete_buffer(Buffer& buffer) { return p.get() == &buffer; }); kak_assert(it != m_buffers.end()); + ClientManager::instance().ensure_no_client_uses_buffer(buffer); m_buffer_trash.emplace_back(std::move(*it)); m_buffers.erase(it); + + buffer.on_unregistered(); } Buffer* BufferManager::get_buffer_ifp(StringView name) diff --git a/src/main.cc b/src/main.cc index 82444571..2ebeb632 100644 --- a/src/main.cc +++ b/src/main.cc @@ -664,11 +664,11 @@ int run_filter(StringView keystr, StringView commands, ConstArrayView