From 62b06fa427b4f432f82510f51e4b6920280b17a8 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Wed, 14 Dec 2016 22:38:37 +0100 Subject: [PATCH] Add a trash pool for invalidation requests. While EventLoop::invalidate_request() does invalidate request in the request-list. It does *not* invalidate requests in the per-thread-request-ringbuffer(s). The invalidation record cannot be deleted in EventLoop::invalidate_request see 6b5891a78f. --- libs/pbd/event_loop.cc | 5 +++-- libs/pbd/pbd/abstract_ui.cc | 21 +++++++++++++++++---- libs/pbd/pbd/event_loop.h | 2 ++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libs/pbd/event_loop.cc b/libs/pbd/event_loop.cc index 0baba2835a..aae0c21a08 100644 --- a/libs/pbd/event_loop.cc +++ b/libs/pbd/event_loop.cc @@ -95,8 +95,9 @@ EventLoop::invalidate_request (void* data) (*i)->invalidation = 0; } } - // should this not always be deleted, regardless if there's an event_loop? - delete ir; + // This invalidation record may still be in-use in per-thread-request-ringbuffer. + // it cannot be deleted here, + ir->event_loop->trash.push_back(ir); } else { DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("EventLoop::invalidate_request no event-loop for invalidation %1\n", ir)); } diff --git a/libs/pbd/pbd/abstract_ui.cc b/libs/pbd/pbd/abstract_ui.cc index db63c3f96d..db7ce38a64 100644 --- a/libs/pbd/pbd/abstract_ui.cc +++ b/libs/pbd/pbd/abstract_ui.cc @@ -218,6 +218,7 @@ AbstractUI::handle_ui_requests () if (vec.len[0] == 0) { break; } else { + bool alive = true; if (vec.buf[0]->valid ()) { /* We first need to remove the event from the list. * If the event results in object destruction, PBD::EventLoop::invalidate_request @@ -225,6 +226,7 @@ AbstractUI::handle_ui_requests () */ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: remove request %2 from its invalidation list %3\n", event_loop_name(), vec.buf[0], vec.buf[0]->invalidation)); if (vec.buf[0]->invalidation) { + alive = std::find (trash.begin(), trash.end(), vec.buf[0]->invalidation) == trash.end(); DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: removing invalidation record for that request\n", event_loop_name())); if (vec.buf[0]->invalidation->event_loop && vec.buf[0]->invalidation->event_loop != this) { vec.buf[0]->invalidation->event_loop->slot_invalidation_mutex().lock (); @@ -240,8 +242,12 @@ AbstractUI::handle_ui_requests () DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: valid request, unlocking before calling\n", event_loop_name())); rbml.release (); - DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: valid request, calling ::do_request()\n", event_loop_name())); - do_request (vec.buf[0]); + if (alive) { + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: valid request, calling ::do_request()\n", event_loop_name())); + do_request (vec.buf[0]); + } else { + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: skipping invalidated request\n", event_loop_name())); + } /* if the request was CallSlot, then we need to ensure that we reset the functor in the request, in case it * held a shared_ptr<>. Failure to do so can lead to dangling references to objects passed to PBD::Signals. @@ -264,8 +270,6 @@ AbstractUI::handle_ui_requests () } } - /* clean up any dead request buffers (their thread has exited) */ - assert (rbml.locked ()); for (i = request_buffers.begin(); i != request_buffers.end(); ) { if ((*i).second->dead) { @@ -370,6 +374,15 @@ AbstractUI::handle_ui_requests () rbml.acquire(); } + /* clean up any dead invalidation records (object was deleted) */ + trash.sort(); + trash.unique(); + for (std::list::const_iterator r = trash.begin(); r != trash.end(); ++r) { + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1 drop invalidation trash %2\n", event_loop_name(), *r)); + delete *r; + } + trash.clear (); + rbml.release (); } diff --git a/libs/pbd/pbd/event_loop.h b/libs/pbd/pbd/event_loop.h index 6fd92c49c8..e84832ebcb 100644 --- a/libs/pbd/pbd/event_loop.h +++ b/libs/pbd/pbd/event_loop.h @@ -99,6 +99,8 @@ public: static void pre_register (const std::string& emitting_thread_name, uint32_t num_requests); static void remove_request_buffer_from_map (void* ptr); + std::list trash; + private: static Glib::Threads::Private thread_event_loop; std::string _name;