Integrated FSM and message router classes.

This commit is contained in:
John Wellbelove 2017-07-02 12:44:01 +01:00
parent 7bdca60d1a
commit 7db12ea0fd
5 changed files with 582 additions and 169 deletions

181
src/fsm.h
View File

@ -37,10 +37,16 @@ SOFTWARE.
#include "exception.h"
#include "user_type.h"
#include "message_router.h"
#include "integral_limits.h"
#include "largest.h"
#undef ETL_FILE
#define ETL_FILE "34"
#ifdef ETL_COMPILER_MICROSOFT
#undef max
#endif
namespace etl
{
/// Allow alternative type for state id.
@ -50,7 +56,8 @@ namespace etl
typedef ETL_FSM_STATE_ID_TYPE fsm_state_id_t;
#endif
typedef etl::imessage::id_t fsm_event_id_t;
// For internal FSM use.
typedef typename etl::larger_type<etl::message_id_t>::type fsm_internal_id_t;
//***************************************************************************
/// Base exception class for FSM.
@ -111,7 +118,8 @@ namespace etl
{
public:
friend class fsm;
/// Allows ifsm_state functions to be private.
friend class fsm_helper;
//*******************************************
/// Gets the id for this state.
@ -119,12 +127,10 @@ namespace etl
etl::fsm_state_id_t get_state_id() const
{
return state_id;
}
}
protected:
virtual fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) = 0;
//*******************************************
/// Constructor.
//*******************************************
@ -133,11 +139,13 @@ namespace etl
{
}
private:
virtual fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) = 0;
virtual void on_enter_state() {}; // By default, do nothing.
virtual void on_exit_state() {}; // By default, do nothing.
private:
// The state id.
const etl::fsm_state_id_t state_id;
@ -147,7 +155,57 @@ namespace etl
};
//***************************************************************************
class fsm : public etl::imessage_router
/// Helper class for FSM.
/// Allows ifsm_state functions to be private.
//***************************************************************************
class fsm_helper
{
public:
//*******************************************
inline fsm_state_id_t process_event(etl::ifsm_state& state,
etl::imessage_router& source,
const etl::imessage& message)
{
return state.process_event(source, message);
}
//*******************************************
inline void on_enter_state(etl::ifsm_state &state)
{
state.on_enter_state();
}
//*******************************************
inline void on_exit_state(etl::ifsm_state &state)
{
state.on_exit_state();
}
};
//***************************************************************************
// The code below has been auto generated. Do not manually edit.
//***************************************************************************
template <const fsm_internal_id_t ID1 = etl::integral_limits<fsm_internal_id_t>::max - 0,
const fsm_internal_id_t ID2 = etl::integral_limits<fsm_internal_id_t>::max - 1,
const fsm_internal_id_t ID3 = etl::integral_limits<fsm_internal_id_t>::max - 2,
const fsm_internal_id_t ID4 = etl::integral_limits<fsm_internal_id_t>::max - 3,
const fsm_internal_id_t ID5 = etl::integral_limits<fsm_internal_id_t>::max - 4,
const fsm_internal_id_t ID6 = etl::integral_limits<fsm_internal_id_t>::max - 5,
const fsm_internal_id_t ID7 = etl::integral_limits<fsm_internal_id_t>::max - 6,
const fsm_internal_id_t ID8 = etl::integral_limits<fsm_internal_id_t>::max - 7,
const fsm_internal_id_t ID9 = etl::integral_limits<fsm_internal_id_t>::max - 8,
const fsm_internal_id_t ID10 = etl::integral_limits<fsm_internal_id_t>::max - 9,
const fsm_internal_id_t ID11 = etl::integral_limits<fsm_internal_id_t>::max - 10,
const fsm_internal_id_t ID12 = etl::integral_limits<fsm_internal_id_t>::max - 11,
const fsm_internal_id_t ID13 = etl::integral_limits<fsm_internal_id_t>::max - 12,
const fsm_internal_id_t ID14 = etl::integral_limits<fsm_internal_id_t>::max - 13,
const fsm_internal_id_t ID15 = etl::integral_limits<fsm_internal_id_t>::max - 14,
const fsm_internal_id_t ID16 = etl::integral_limits<fsm_internal_id_t>::max - 15>
//***************************************************************************
// The code above has been auto generated. Do not manually edit.
//***************************************************************************
class fsm : public etl::imessage_router , protected etl::fsm_helper
{
public:
@ -192,7 +250,7 @@ namespace etl
p_state = state_list[0];
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
p_state->on_enter_state();
fsm_helper::on_enter_state(*p_state);
}
}
@ -204,24 +262,55 @@ namespace etl
receive(etl::null_message_router(), message);
}
//*******************************************
void receive(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t next_state_id = p_state->process_event(source, message);
etl::fsm_state_id_t next_state_id = fsm_helper::process_event(*p_state, source, message);
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
// Have we changed state?
if (next_state_id != p_state->get_state_id())
{
p_state->on_exit_state();
//p_state->on_exit_state();
fsm_helper::on_exit_state(*p_state);
p_state = state_list[next_state_id];
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
p_state->on_enter_state();
fsm_helper::on_enter_state(*p_state);
}
}
//*******************************************
/// Does this FSM accept the message?
//*******************************************
bool accepts(const etl::imessage& msg) const
{
return accepts(msg.get_message_id());
}
//*******************************************
/// Does this FSM accept the message id?
//*******************************************
bool accepts(etl::message_id_t id) const
{
//***************************************************************************
// The code below has been auto generated. Do not manually edit.
//***************************************************************************
switch (fsm_internal_id_t(id))
{
case ID1: case ID2: case ID3: case ID4: case ID5: case ID6: case ID7: case ID8:
case ID9: case ID10: case ID11: case ID12: case ID13: case ID14: case ID15: case ID16:
return true; break;
default:
return false; break;
}
//***************************************************************************
// The code above has been auto generated. Do not manually edit.
//***************************************************************************
}
//*******************************************
/// Gets the current state id.
//*******************************************
@ -310,8 +399,6 @@ namespace etl
{
public:
friend class fsm;
enum
{
STATE_ID = STATE_ID_
@ -325,7 +412,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -363,8 +450,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -379,7 +464,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -416,8 +501,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -432,7 +515,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -468,8 +551,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, void, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -484,7 +565,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -518,8 +599,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, void, void, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -534,7 +613,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -567,8 +646,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, void, void, void, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -583,7 +660,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -615,8 +692,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, void, void, void, void, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -631,7 +706,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -662,8 +737,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, void, void, void, void, void, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -678,7 +751,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -707,8 +780,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, void, void, void, void, void, void, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -723,7 +794,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -751,8 +822,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, void, void, void, void, void, void, void, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -767,7 +836,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -794,8 +863,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, T3, T4, T5, T6, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -810,7 +877,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -836,8 +903,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, T3, T4, T5, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -852,7 +917,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -876,8 +941,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, T3, T4, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -892,7 +955,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -915,8 +978,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, T3, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -931,7 +992,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -953,8 +1014,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, T2, void, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -969,7 +1028,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -990,8 +1049,6 @@ namespace etl
class fsm_state<TState, STATE_ID_, T1, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
{
public:
friend class fsm;
enum
{
@ -1006,7 +1063,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::fsm_event_id_t event_id = message.get_message_id();
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -1021,4 +1078,8 @@ namespace etl
#undef ETL_FILE
#ifdef ETL_COMPILER_MICROSOFT
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#endif

View File

@ -37,10 +37,16 @@ SOFTWARE.
#include "exception.h"
#include "user_type.h"
#include "message_router.h"
#include "integral_limits.h"
#include "largest.h"
#undef ETL_FILE
#define ETL_FILE "34"
#ifdef ETL_COMPILER_MICROSOFT
#undef max
#endif
namespace etl
{
/// Allow alternative type for state id.
@ -50,7 +56,8 @@ namespace etl
typedef ETL_FSM_STATE_ID_TYPE fsm_state_id_t;
#endif
typedef etl::imessage::id_t fsm_event_id_t;
// For internal FSM use.
typedef typename etl::larger_type<etl::message_id_t>::type fsm_internal_id_t;
//***************************************************************************
/// Base exception class for FSM.
@ -111,7 +118,8 @@ namespace etl
{
public:
friend class fsm;
/// Allows ifsm_state functions to be private.
friend class fsm_helper;
//*******************************************
/// Gets the id for this state.
@ -119,12 +127,10 @@ namespace etl
etl::fsm_state_id_t get_state_id() const
{
return state_id;
}
}
protected:
virtual fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) = 0;
//*******************************************
/// Constructor.
//*******************************************
@ -133,11 +139,13 @@ namespace etl
{
}
private:
virtual fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) = 0;
virtual void on_enter_state() {}; // By default, do nothing.
virtual void on_exit_state() {}; // By default, do nothing.
private:
// The state id.
const etl::fsm_state_id_t state_id;
@ -147,7 +155,51 @@ namespace etl
};
//***************************************************************************
class fsm : public etl::imessage_router
/// Helper class for FSM.
/// Allows ifsm_state functions to be private.
//***************************************************************************
class fsm_helper
{
public:
//*******************************************
inline fsm_state_id_t process_event(etl::ifsm_state& state,
etl::imessage_router& source,
const etl::imessage& message)
{
return state.process_event(source, message);
}
//*******************************************
inline void on_enter_state(etl::ifsm_state &state)
{
state.on_enter_state();
}
//*******************************************
inline void on_exit_state(etl::ifsm_state &state)
{
state.on_exit_state();
}
};
/*[[[cog
import cog
cog.outl("//***************************************************************************")
cog.outl("// The code below has been auto generated. Do not manually edit.")
cog.outl("//***************************************************************************")
cog.out("template <")
for n in range(1, int(Handlers)):
cog.outl("const fsm_internal_id_t ID%d = etl::integral_limits<fsm_internal_id_t>::max - %d, " % (n, n - 1))
cog.out(" ")
cog.out("const fsm_internal_id_t ID%d = etl::integral_limits<fsm_internal_id_t>::max - %d" % (int(Handlers), int(Handlers) - 1))
cog.outl(">")
cog.outl("//***************************************************************************")
cog.outl("// The code above has been auto generated. Do not manually edit.")
cog.outl("//***************************************************************************")
]]]*/
/*[[[end]]]*/
class fsm : public etl::imessage_router , protected etl::fsm_helper
{
public:
@ -192,7 +244,7 @@ namespace etl
p_state = state_list[0];
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
p_state->on_enter_state();
fsm_helper::on_enter_state(*p_state);
}
}
@ -204,24 +256,63 @@ namespace etl
receive(etl::null_message_router(), message);
}
//*******************************************
void receive(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t next_state_id = p_state->process_event(source, message);
etl::fsm_state_id_t next_state_id = fsm_helper::process_event(*p_state, source, message);
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
// Have we changed state?
if (next_state_id != p_state->get_state_id())
{
p_state->on_exit_state();
//p_state->on_exit_state();
fsm_helper::on_exit_state(*p_state);
p_state = state_list[next_state_id];
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
p_state->on_enter_state();
fsm_helper::on_enter_state(*p_state);
}
}
//*******************************************
/// Does this FSM accept the message?
//*******************************************
bool accepts(const etl::imessage& msg) const
{
return accepts(msg.get_message_id());
}
//*******************************************
/// Does this FSM accept the message id?
//*******************************************
bool accepts(etl::message_id_t id) const
{
/*[[[cog
import cog
cog.outl("//***************************************************************************")
cog.outl("// The code below has been auto generated. Do not manually edit.")
cog.outl("//***************************************************************************")
cog.outl("switch (fsm_internal_id_t(id))")
cog.outl("{")
cog.out(" ")
for n in range(1, int(Handlers) + 1):
cog.out("case ID%d: " % n)
if n % 8 == 0:
cog.outl("")
cog.out(" ")
cog.outl(" return true; break;")
cog.outl(" default:")
cog.outl(" return false; break;")
cog.outl("}")
cog.outl("//***************************************************************************")
cog.outl("// The code above has been auto generated. Do not manually edit.")
cog.outl("//***************************************************************************")
]]]*/
/*[[[end]]]*/
}
//*******************************************
/// Gets the current state id.
//*******************************************
@ -318,10 +409,6 @@ namespace etl
cog.outl("{")
cog.outl("public:")
cog.outl("")
cog.outl(" friend class fsm;")
cog.outl("")
cog.outl(" enum")
cog.outl(" {")
cog.outl(" STATE_ID = STATE_ID_")
@ -335,7 +422,7 @@ namespace etl
cog.outl(" etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)")
cog.outl(" {")
cog.outl(" etl::fsm_state_id_t new_state_id;")
cog.outl(" etl::fsm_event_id_t event_id = message.get_message_id();")
cog.outl(" etl::message_id_t event_id = message.get_message_id();")
cog.outl("")
cog.outl(" switch (event_id)")
cog.outl(" {")
@ -385,10 +472,6 @@ namespace etl
cog.outl("void> : public ifsm_state")
cog.outl("{")
cog.outl("public:")
cog.outl(" friend class fsm;")
cog.outl("")
cog.outl("")
cog.outl(" enum")
cog.outl(" {")
@ -403,7 +486,7 @@ namespace etl
cog.outl(" etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)")
cog.outl(" {")
cog.outl(" etl::fsm_state_id_t new_state_id;")
cog.outl(" etl::fsm_event_id_t event_id = message.get_message_id();")
cog.outl(" etl::message_id_t event_id = message.get_message_id();")
cog.outl("")
cog.outl(" switch (event_id)")
cog.outl(" {")
@ -425,4 +508,8 @@ namespace etl
#undef ETL_FILE
#ifdef ETL_COMPILER_MICROSOFT
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#endif

View File

@ -33,20 +33,20 @@ SOFTWARE.
namespace etl
{
/// Allow alternative type for message id.
#if !defined(ETL_MESSAGE_ID_TYPE)
typedef uint_least8_t message_id_t;
#else
typedef ETL_MESSAGE_ID_TYPE message_id_t;
#endif
//***************************************************************************
class imessage
{
public:
/// Allow alternative type for message id.
#if !defined(ETL_MESSAGE_ID_TYPE)
typedef uint_least8_t id_t;
#else
typedef ETL_MESSAGE_ID_TYPE id_t;
#endif
virtual ~imessage() {}
virtual id_t get_message_id() const = 0;
virtual etl::message_id_t get_message_id() const = 0;
};
//***************************************************************************
@ -60,9 +60,9 @@ namespace etl
ID = ID_
};
id_t get_message_id() const
etl::message_id_t get_message_id() const
{
return id_t(ID);
return etl::message_id_t(ID);
}
};
@ -71,11 +71,18 @@ namespace etl
{
public:
virtual ~imessage_router() {}
virtual void receive(const imessage& message) = 0;
virtual void receive(imessage_router& source, const imessage& message) = 0;
virtual void receive(const etl::imessage& message) = 0;
virtual void receive(imessage_router& source, const etl::imessage& message) = 0;
virtual bool accepts(etl::message_id_t id) const = 0;
bool accepts(const etl::imessage& msg) const
{
return accepts(msg.get_message_id());
}
void send_message(imessage_router& destination,
const imessage& message)
const etl::imessage& message)
{
destination.receive(*this, message);
}
@ -89,21 +96,26 @@ namespace etl
{
public:
void receive(const imessage& message)
void receive(const etl::imessage& message)
{
}
void receive(imessage_router& source, const imessage& message)
void receive(etl::imessage_router& source, const etl::imessage& message)
{
}
bool accepts(etl::message_id_t id) const
{
return false;
}
};
//***************************************************************************
/// Send a message to a router.
/// Sets the 'sender' to etl::null_message_router type.
//***************************************************************************
inline static void send_message(imessage_router& destination,
const imessage& message)
inline static void send_message(etl::imessage_router& destination,
const etl::imessage& message)
{
destination.receive(message);
}
@ -111,9 +123,9 @@ namespace etl
//***************************************************************************
/// Send a message to a router.
//***************************************************************************
inline static void send_message(imessage_router& source,
imessage_router& destination,
const imessage& message)
inline static void send_message(etl::imessage_router& source,
etl::imessage_router& destination,
const etl::imessage& message)
{
destination.receive(source, message);
}
@ -148,14 +160,14 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const id_t id = msg.get_message_id();
const etl::message_id_t id = msg.get_message_id();
switch (id)
{
@ -178,6 +190,18 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: case T16::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -193,12 +217,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -222,6 +246,18 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -237,12 +273,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -265,6 +301,18 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -280,12 +328,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -307,6 +355,18 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -321,12 +381,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -347,6 +407,18 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID: case T11::ID: case T12::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -361,12 +433,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -386,6 +458,18 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID: case T11::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -400,12 +484,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -424,6 +508,18 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -438,12 +534,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -461,6 +557,18 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -474,12 +582,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -496,6 +604,18 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -509,12 +629,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -530,6 +650,17 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -543,12 +674,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -563,6 +694,17 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -576,12 +718,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -595,6 +737,17 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -607,12 +760,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -625,6 +778,17 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -637,12 +801,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -654,6 +818,17 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -666,12 +841,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -682,6 +857,17 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
@ -694,12 +880,12 @@ namespace etl
{
public:
void receive(const imessage& msg)
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router(), msg);
}
void receive(imessage_router& source, const imessage& msg)
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
@ -709,6 +895,17 @@ namespace etl
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID:
return true; break;
default:
return false; break;
}
}
};
}

View File

@ -33,20 +33,20 @@ SOFTWARE.
namespace etl
{
/// Allow alternative type for message id.
#if !defined(ETL_MESSAGE_ID_TYPE)
typedef uint_least8_t message_id_t;
#else
typedef ETL_MESSAGE_ID_TYPE message_id_t;
#endif
//***************************************************************************
class imessage
{
public:
/// Allow alternative type for message id.
#if !defined(ETL_MESSAGE_ID_TYPE)
typedef uint_least8_t id_t;
#else
typedef ETL_MESSAGE_ID_TYPE id_t;
#endif
virtual ~imessage() {}
virtual id_t get_message_id() const = 0;
virtual etl::message_id_t get_message_id() const = 0;
};
//***************************************************************************
@ -60,9 +60,9 @@ namespace etl
ID = ID_
};
id_t get_message_id() const
etl::message_id_t get_message_id() const
{
return id_t(ID);
return etl::message_id_t(ID);
}
};
@ -71,11 +71,18 @@ namespace etl
{
public:
virtual ~imessage_router() {}
virtual void receive(const imessage& message) = 0;
virtual void receive(imessage_router& source, const imessage& message) = 0;
virtual void receive(const etl::imessage& message) = 0;
virtual void receive(imessage_router& source, const etl::imessage& message) = 0;
virtual bool accepts(etl::message_id_t id) const = 0;
bool accepts(const etl::imessage& msg) const
{
return accepts(msg.get_message_id());
}
void send_message(imessage_router& destination,
const imessage& message)
const etl::imessage& message)
{
destination.receive(*this, message);
}
@ -89,21 +96,26 @@ namespace etl
{
public:
void receive(const imessage& message)
void receive(const etl::imessage& message)
{
}
void receive(imessage_router& source, const imessage& message)
void receive(etl::imessage_router& source, const etl::imessage& message)
{
}
bool accepts(etl::message_id_t id) const
{
return false;
}
};
//***************************************************************************
/// Send a message to a router.
/// Sets the 'sender' to etl::null_message_router type.
//***************************************************************************
inline static void send_message(imessage_router& destination,
const imessage& message)
inline static void send_message(etl::imessage_router& destination,
const etl::imessage& message)
{
destination.receive(message);
}
@ -111,9 +123,9 @@ namespace etl
//***************************************************************************
/// Send a message to a router.
//***************************************************************************
inline static void send_message(imessage_router& source,
imessage_router& destination,
const imessage& message)
inline static void send_message(etl::imessage_router& source,
etl::imessage_router& destination,
const etl::imessage& message)
{
destination.receive(source, message);
}
@ -158,14 +170,14 @@ namespace etl
cog.outl("{")
cog.outl("public:")
cog.outl("")
cog.outl(" void receive(const imessage& msg)")
cog.outl(" void receive(const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" receive(etl::null_message_router(), msg);")
cog.outl(" }")
cog.outl("")
cog.outl(" void receive(imessage_router& source, const imessage& msg)")
cog.outl(" void receive(etl::imessage_router& source, const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" const id_t id = msg.get_message_id();")
cog.outl(" const etl::message_id_t id = msg.get_message_id();")
cog.outl("")
cog.outl(" switch (id)")
cog.outl(" {")
@ -178,6 +190,22 @@ namespace etl
cog.outl(" break;")
cog.outl(" }")
cog.outl(" }")
cog.outl("")
cog.outl(" bool accepts(etl::message_id_t id) const")
cog.outl(" {")
cog.outl(" switch (id)")
cog.outl(" {")
cog.out(" ")
for n in range(1, int(Handlers) + 1):
cog.out("case T%d::ID: " % n)
if n % 8 == 0:
cog.outl("")
cog.out(" ")
cog.outl(" return true; break;")
cog.outl(" default:")
cog.outl(" return false; break;")
cog.outl(" }")
cog.outl(" }")
cog.outl("};")
####################################
@ -215,12 +243,12 @@ namespace etl
cog.outl("{")
cog.outl("public:")
cog.outl("")
cog.outl(" void receive(const imessage& msg)")
cog.outl(" void receive(const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" receive(etl::null_message_router(), msg);")
cog.outl(" }")
cog.outl("")
cog.outl(" void receive(imessage_router& source, const imessage& msg)")
cog.outl(" void receive(etl::imessage_router& source, const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" const size_t id = msg.get_message_id();")
cog.outl("")
@ -235,6 +263,23 @@ namespace etl
cog.outl(" break;")
cog.outl(" }")
cog.outl(" }")
cog.outl("")
cog.outl(" bool accepts(etl::message_id_t id) const")
cog.outl(" {")
cog.outl(" switch (id)")
cog.outl(" {")
cog.out(" ")
for t in range(1, n + 1):
cog.out("case T%d::ID: " % t)
if t % 8 == 0:
cog.outl("")
cog.out(" ")
cog.outl("")
cog.outl(" return true; break;")
cog.outl(" default:")
cog.outl(" return false; break;")
cog.outl(" }")
cog.outl(" }")
cog.outl("};")
]]]*/
/*[[[end]]]*/

View File

@ -45,14 +45,16 @@ namespace
START,
STOP,
STOPPED,
SET_SPEED
SET_SPEED,
UNSUPPORTED
};
ETL_DECLARE_ENUM_TYPE(EventId, etl::fsm_event_id_t)
ETL_ENUM_TYPE(START, "Start")
ETL_ENUM_TYPE(STOP, "Stop")
ETL_ENUM_TYPE(STOPPED, "Stopped")
ETL_ENUM_TYPE(SET_SPEED, "Set Speed")
ETL_DECLARE_ENUM_TYPE(EventId, etl::message_id_t)
ETL_ENUM_TYPE(START, "Start")
ETL_ENUM_TYPE(STOP, "Stop")
ETL_ENUM_TYPE(STOPPED, "Stopped")
ETL_ENUM_TYPE(SET_SPEED, "Set Speed")
ETL_ENUM_TYPE(UNSUPPORTED, "Unsupported")
ETL_END_ENUM_TYPE
};
@ -87,6 +89,11 @@ namespace
{
};
//***********************************
class Unsupported : public etl::message<EventId::UNSUPPORTED>
{
};
//***************************************************************************
// States
struct StateId
@ -280,7 +287,7 @@ namespace
//***********************************
// The motor control FSM.
//***********************************
class MotorControl : public etl::fsm
class MotorControl : public etl::fsm<EventId::SET_SPEED, EventId::START, EventId::STOP, EventId::STOPPED>
{
public:
@ -494,5 +501,21 @@ namespace
CHECK_EQUAL(0, motorControl.common.stoppedCount);
CHECK_EQUAL(0, motorControl.common.unknownCount);
}
//*************************************************************************
TEST(test_fsm_supported)
{
CHECK(motorControl.accepts(EventId::SET_SPEED));
CHECK(motorControl.accepts(EventId::START));
CHECK(motorControl.accepts(EventId::STOP));
CHECK(motorControl.accepts(EventId::STOPPED));
CHECK(!motorControl.accepts(EventId::UNSUPPORTED));
CHECK(motorControl.accepts(SetSpeed(0)));
CHECK(motorControl.accepts(Start()));
CHECK(motorControl.accepts(Stop()));
CHECK(motorControl.accepts(Stopped()));
CHECK(!motorControl.accepts(Unsupported()));
}
};
}