13
0

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.
This commit is contained in:
Robin Gareus 2016-12-14 22:38:37 +01:00
parent 07bcdc7f0a
commit 62b06fa427
3 changed files with 22 additions and 6 deletions

View File

@ -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));
}

View File

@ -218,6 +218,7 @@ AbstractUI<RequestObject>::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<RequestObject>::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<RequestObject>::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<RequestObject>::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<RequestObject>::handle_ui_requests ()
rbml.acquire();
}
/* clean up any dead invalidation records (object was deleted) */
trash.sort();
trash.unique();
for (std::list<InvalidationRecord*>::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 ();
}

View File

@ -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<InvalidationRecord*> trash;
private:
static Glib::Threads::Private<EventLoop> thread_event_loop;
std::string _name;