- while (true) {
-
- /* we must process requests 1 by 1 because
- the request may run a recursive main
- event loop that will itself call
- handle_ui_requests. when we return
- from the request handler, we cannot
- expect that the state of queued requests
- is even remotely consistent with
- the condition before we called it.
- */
-
- i->second->get_read_vector (&vec);
-
- if (vec.len[0] == 0) {
- break;
- } else {
- if (vec.buf[0]->valid) {
- request_buffer_map_lock.unlock ();
- do_request (vec.buf[0]);
- request_buffer_map_lock.lock ();
- if (vec.buf[0]->invalidation) {
- vec.buf[0]->invalidation->requests.remove (vec.buf[0]);
- }
- i->second->increment_read_ptr (1);
- }
- }
- }
- }
-
- /* clean up any dead request buffers (their thread has exited) */
+ while (true) {
+
+ /* we must process requests 1 by 1 because
+ * the request may run a recursive main
+ * event loop that will itself call
+ * handle_ui_requests. when we return
+ * from the request handler, we cannot
+ * expect that the state of queued requests
+ * is even remotely consistent with
+ * the condition before we called it.
+ */
+
+ i->second->get_read_vector (&vec);
+
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1 reading requests from RB[%2] @ %5, requests = %3 + %4\n",
+ event_loop_name(), std::distance (request_buffers.begin(), i), vec.len[0], vec.len[1], i->second));
+
+ if (vec.len[0] == 0) {
+ break;
+ } else {
+ if (vec.buf[0]->valid) {
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: valid request, unlocking before calling\n", event_loop_name()));
+ request_buffer_map_lock.unlock ();
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: valid request, calling ::do_request()\n", event_loop_name()));
+ do_request (vec.buf[0]);
+
+ /* 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.
+ *
+ * Note that this method (::handle_ui_requests()) is by definition called from the event loop thread, so
+ * caller_is_self() is true, which means that the execution of the functor has definitely happened after
+ * do_request() returns and we no longer need the functor for any reason.
+ */
+
+ if (vec.buf[0]->type == CallSlot) {
+ vec.buf[0]->the_slot = 0;
+ }
+
+ request_buffer_map_lock.lock ();
+ if (vec.buf[0]->invalidation) {
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: removing invalidation record for that request\n", event_loop_name()));
+ vec.buf[0]->invalidation->requests.remove (vec.buf[0]);
+ } else {
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: no invalidation record for that request\n", event_loop_name()));
+ }
+ } else {
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, "invalid request, ignoring\n");
+ }
+ i->second->increment_read_ptr (1);
+ }
+ }
+ }
+
+ /* clean up any dead request buffers (their thread has exited) */