From c368c26519d05815e9bfadbd02f9de5f5d84321c Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 29 Oct 2019 16:15:38 -0600 Subject: fix handling of deferred events in transportFSM tfsm events live on intrusive lists, with only 1 hook, which means they can only be on one list at a time, and cannot be deleted while part of the list. This wasn't being addressed properly when deferring (and undeferring) events. --- libs/ardour/ardour/transport_fsm.h | 2 +- libs/ardour/transport_fsm.cc | 48 +++++++++++++++++++++++++++++++------- 2 files changed, 40 insertions(+), 10 deletions(-) (limited to 'libs/ardour') diff --git a/libs/ardour/ardour/transport_fsm.h b/libs/ardour/ardour/transport_fsm.h index 922f910a12..869611a8ab 100644 --- a/libs/ardour/ardour/transport_fsm.h +++ b/libs/ardour/ardour/transport_fsm.h @@ -159,7 +159,7 @@ struct TransportFSM void transition (ButlerState bs); void process_events (); - bool process_event (Event&); + bool process_event (Event&, bool was_deferred, bool& deferred); Event _last_locate; Event _last_stop; diff --git a/libs/ardour/transport_fsm.cc b/libs/ardour/transport_fsm.cc index 2fd61a3d00..c8b5c65035 100644 --- a/libs/ardour/transport_fsm.cc +++ b/libs/ardour/transport_fsm.cc @@ -80,7 +80,19 @@ TransportFSM::process_events () MotionState oms = _motion_state; ButlerState obs = _butler_state; - if (process_event (queued_events.front())) { /* event processed successfully */ + Event* ev = &queued_events.front(); + bool deferred; + + /* must remove from the queued_events list now, because + * process_event() may defer the event. This will lead to + * insertion into the deferred_events list, and its not possible + * with intrusive lists to be present in two lists at once + * (without additional hooks). + */ + + queued_events.pop_front (); + + if (process_event (*ev, false, deferred)) { /* event processed successfully */ if (oms != _motion_state || obs != _butler_state) { @@ -93,7 +105,8 @@ TransportFSM::process_events () for (EventList::iterator e = deferred_events.begin(); e != deferred_events.end(); ) { Event* deferred_ev = &(*e); - if (process_event (*e)) { /* event processed, remove from deferred */ + bool deferred2; + if (process_event (*e, true, deferred2)) { /* event processed, remove from deferred */ e = deferred_events.erase (e); delete deferred_ev; } else { @@ -104,9 +117,9 @@ TransportFSM::process_events () } } - Event* ev = &queued_events.front(); - queued_events.pop_front (); - delete ev; + if (!deferred) { + delete ev; + } } processing--; @@ -178,10 +191,12 @@ TransportFSM::bad_transition (Event const & ev) } bool -TransportFSM::process_event (Event& ev) +TransportFSM::process_event (Event& ev, bool already_deferred, bool& deferred) { DEBUG_TRACE (DEBUG::TFSMEvents, string_compose ("process %1\n", enum_2_string (ev.type))); + deferred = false; + switch (ev.type) { case StartTransport: @@ -194,10 +209,16 @@ TransportFSM::process_event (Event& ev) break; case DeclickToLocate: case WaitingForLocate: - defer (ev); + if (!already_deferred) { + defer (ev); + deferred = true; + } break; case DeclickToStop: - defer (ev); + if (!already_deferred) { + defer (ev); + deferred = true; + } break; default: bad_transition (ev); return false; @@ -215,7 +236,10 @@ TransportFSM::process_event (Event& ev) break; case DeclickToLocate: case WaitingForLocate: - defer (ev); + if (!already_deferred) { + defer (ev); + deferred = true; + } break; default: bad_transition (ev); return false; @@ -224,6 +248,12 @@ TransportFSM::process_event (Event& ev) break; case Locate: + DEBUG_TRACE (DEBUG::TFSMEvents, string_compose ("locate, with roll = %1 flush = %2 target = %3 loop %4 force %5\n", + ev.with_roll, + ev.with_flush, + ev.target, + ev.with_loop, + ev.force)); switch (_motion_state) { case Stopped: transition (WaitingForLocate); -- cgit v1.2.3