13
0

use boost::intrusive to manage FSM events (this is all RT code)

This commit is contained in:
Paul Davis 2019-09-20 09:33:24 -06:00
parent ea8ec74565
commit b075c67e51
2 changed files with 44 additions and 38 deletions

View File

@ -4,6 +4,11 @@
#include <list> #include <list>
#include <queue> #include <queue>
#include <boost/intrusive/list.hpp>
#include <string>
#include <utility>
#include <iostream>
#include "pbd/demangle.h" #include "pbd/demangle.h"
#include "pbd/stacktrace.h" #include "pbd/stacktrace.h"
@ -30,7 +35,7 @@ struct TransportFSM
LocateDone LocateDone
}; };
struct FSMEvent { struct FSMEvent : public boost::intrusive::list_base_hook<> {
EventType type; EventType type;
union { union {
bool abort; /* for stop */ bool abort; /* for stop */
@ -122,10 +127,10 @@ struct TransportFSM
void stop_playback (); void stop_playback ();
void start_saved_locate (); void start_saved_locate ();
void roll_after_locate (); void roll_after_locate ();
void start_locate (FSMEvent const *); void start_locate (FSMEvent const &);
void interrupt_locate (FSMEvent const *); void interrupt_locate (FSMEvent const &);
void save_locate_and_start_declick (FSMEvent const *); void save_locate_and_start_declick (FSMEvent const &);
void start_declick (FSMEvent const *); void start_declick (FSMEvent const &);
/* guards */ /* guards */
@ -140,7 +145,7 @@ struct TransportFSM
bool declick_in_progress() { return _motion_state == DeclickToLocate || _motion_state == DeclickToStop; } bool declick_in_progress() { return _motion_state == DeclickToLocate || _motion_state == DeclickToStop; }
void enqueue (FSMEvent* ev) { void enqueue (FSMEvent* ev) {
queued_events.push (ev); queued_events.push_back (*ev);
if (!processing) { if (!processing) {
process_events (); process_events ();
} }
@ -152,18 +157,19 @@ struct TransportFSM
void transition (ButlerState bs); void transition (ButlerState bs);
void process_events (); void process_events ();
bool process_event (FSMEvent *); bool process_event (FSMEvent&);
FSMEvent _last_locate; FSMEvent _last_locate;
FSMEvent _last_stop; FSMEvent _last_stop;
TransportAPI* api; TransportAPI* api;
std::queue<FSMEvent*> queued_events; typedef boost::intrusive::list<FSMEvent> EventList;
std::list<FSMEvent*> deferred_events; EventList queued_events;
EventList deferred_events;
int processing; int processing;
void defer (FSMEvent* ev); void defer (FSMEvent& ev);
void bad_transition (FSMEvent const *); void bad_transition (FSMEvent const &);
}; };
} /* end namespace ARDOUR */ } /* end namespace ARDOUR */

View File

@ -41,7 +41,7 @@ void*
TransportFSM::FSMEvent::operator new (size_t) TransportFSM::FSMEvent::operator new (size_t)
{ {
return pool->alloc(); return pool->alloc();
} }
void void
TransportFSM::FSMEvent::operator delete (void *ptr, size_t /*size*/) TransportFSM::FSMEvent::operator delete (void *ptr, size_t /*size*/)
@ -71,13 +71,11 @@ TransportFSM::process_events ()
processing++; processing++;
while (!queued_events.empty()) { while (!queued_events.empty()) {
FSMEvent* ev = queued_events.front();
queued_events.pop ();
MotionState oms = _motion_state; MotionState oms = _motion_state;
ButlerState obs = _butler_state; ButlerState obs = _butler_state;
if (process_event (ev)) { /* event processed successfully */ if (process_event (queued_events.front())) { /* event processed successfully */
if (oms != _motion_state || obs != _butler_state) { if (oms != _motion_state || obs != _butler_state) {
@ -88,9 +86,9 @@ TransportFSM::process_events ()
if (!deferred_events.empty() ){ if (!deferred_events.empty() ){
DEBUG_TRACE (DEBUG::TFSMEvents, string_compose ("processing %1 deferred events\n", deferred_events.size())); DEBUG_TRACE (DEBUG::TFSMEvents, string_compose ("processing %1 deferred events\n", deferred_events.size()));
for (std::list<FSMEvent*>::iterator e = deferred_events.begin(); e != deferred_events.end(); ) { for (EventList::iterator e = deferred_events.begin(); e != deferred_events.end(); ) {
FSMEvent* deferred_ev = *e; FSMEvent* deferred_ev = &(*e);
if (process_event (deferred_ev)) { /* event processed, remove from deferred */ if (process_event (*e)) { /* event processed, remove from deferred */
e = deferred_events.erase (e); e = deferred_events.erase (e);
delete deferred_ev; delete deferred_ev;
} else { } else {
@ -101,6 +99,8 @@ TransportFSM::process_events ()
} }
} }
FSMEvent* ev = &queued_events.front();
queued_events.pop_front ();
delete ev; delete ev;
} }
@ -166,18 +166,18 @@ TransportFSM::current_state () const
} }
void void
TransportFSM::bad_transition (FSMEvent const * ev) TransportFSM::bad_transition (FSMEvent const & ev)
{ {
error << "bad transition, current state = " << current_state() << " event = " << enum_2_string (ev->type) << endmsg; error << "bad transition, current state = " << current_state() << " event = " << enum_2_string (ev.type) << endmsg;
std::cerr << "bad transition, current state = " << current_state() << " event = " << enum_2_string (ev->type) << std::endl; std::cerr << "bad transition, current state = " << current_state() << " event = " << enum_2_string (ev.type) << std::endl;
} }
bool bool
TransportFSM::process_event (FSMEvent* ev) TransportFSM::process_event (FSMEvent& ev)
{ {
DEBUG_TRACE (DEBUG::TFSMEvents, string_compose ("process %1\n", enum_2_string (ev->type))); DEBUG_TRACE (DEBUG::TFSMEvents, string_compose ("process %1\n", enum_2_string (ev.type)));
switch (ev->type) { switch (ev.type) {
case StartTransport: case StartTransport:
switch (_motion_state) { switch (_motion_state) {
@ -305,11 +305,11 @@ TransportFSM::start_playback ()
} }
void void
TransportFSM::start_declick (FSMEvent const * s) TransportFSM::start_declick (FSMEvent const & s)
{ {
assert (s->type == StopTransport); assert (s.type == StopTransport);
DEBUG_TRACE (DEBUG::TFSMEvents, "tfsm::start_declick\n"); DEBUG_TRACE (DEBUG::TFSMEvents, "tfsm::start_declick\n");
_last_stop = *s; _last_stop = s;
} }
void void
@ -320,20 +320,20 @@ TransportFSM::stop_playback ()
} }
void void
TransportFSM::save_locate_and_start_declick (FSMEvent const * l) TransportFSM::save_locate_and_start_declick (FSMEvent const & l)
{ {
assert (l->type == Locate); assert (l.type == Locate);
DEBUG_TRACE (DEBUG::TFSMEvents, "tfsm::save_locate_and_stop\n"); DEBUG_TRACE (DEBUG::TFSMEvents, "tfsm::save_locate_and_stop\n");
_last_locate = *l; _last_locate = l;
_last_stop = FSMEvent (StopTransport, false, false); _last_stop = FSMEvent (StopTransport, false, false);
} }
void void
TransportFSM::start_locate (FSMEvent const * l) TransportFSM::start_locate (FSMEvent const & l)
{ {
assert (l->type == Locate); assert (l.type == Locate);
DEBUG_TRACE (DEBUG::TFSMEvents, "tfsm::start_locate\n"); DEBUG_TRACE (DEBUG::TFSMEvents, "tfsm::start_locate\n");
api->locate (l->target, l->with_roll, l->with_flush, l->with_loop, l->force); api->locate (l.target, l.with_roll, l.with_flush, l.with_loop, l.force);
} }
void void
@ -344,14 +344,14 @@ TransportFSM::start_saved_locate ()
} }
void void
TransportFSM::interrupt_locate (FSMEvent const * l) TransportFSM::interrupt_locate (FSMEvent const & l)
{ {
assert (l->type == Locate); assert (l.type == Locate);
DEBUG_TRACE (DEBUG::TFSMEvents, "tfsm::interrupt\n"); DEBUG_TRACE (DEBUG::TFSMEvents, "tfsm::interrupt\n");
/* maintain original "with-roll" choice of initial locate, even though /* maintain original "with-roll" choice of initial locate, even though
* we are interrupting the locate to start a new one. * we are interrupting the locate to start a new one.
*/ */
api->locate (l->target, _last_locate.with_roll, l->with_flush, l->with_loop, l->force); api->locate (l.target, _last_locate.with_roll, l.with_flush, l.with_loop, l.force);
} }
void void
@ -376,9 +376,9 @@ TransportFSM::roll_after_locate ()
} }
void void
TransportFSM::defer (FSMEvent* ev) TransportFSM::defer (FSMEvent& ev)
{ {
DEBUG_TRACE (DEBUG::TFSMEvents, string_compose ("Defer %1 during %2\n", enum_2_string (ev->type), current_state())); DEBUG_TRACE (DEBUG::TFSMEvents, string_compose ("Defer %1 during %2\n", enum_2_string (ev.type), current_state()));
deferred_events.push_back (ev); deferred_events.push_back (ev);
} }