mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Changed FSM to be based on message router
This commit is contained in:
parent
efb0a408ce
commit
04a9cb7bba
428
src/fsm_generator.h
Normal file
428
src/fsm_generator.h
Normal file
@ -0,0 +1,428 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
http://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2017 jwellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __ETL_FSM__
|
||||
#define __ETL_FSM__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "array.h"
|
||||
#include "nullptr.h"
|
||||
#include "error_handler.h"
|
||||
#include "exception.h"
|
||||
#include "user_type.h"
|
||||
#include "message_router.h"
|
||||
|
||||
#undef ETL_FILE
|
||||
#define ETL_FILE "34"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
/// Allow alternative type for state id.
|
||||
#if !defined(ETL_FSM_STATE_ID_TYPE)
|
||||
typedef uint_least8_t fsm_state_id_t;
|
||||
#else
|
||||
typedef ETL_FSM_STATE_ID_TYPE fsm_state_id_t;
|
||||
#endif
|
||||
|
||||
typedef etl::imessage::id_t fsm_event_id_t;
|
||||
|
||||
//***************************************************************************
|
||||
/// Base exception class for FSM.
|
||||
//***************************************************************************
|
||||
class fsm_exception : public etl::exception
|
||||
{
|
||||
public:
|
||||
|
||||
fsm_exception(string_type what, string_type file_name, numeric_type line_number)
|
||||
: etl::exception(what, file_name, line_number)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Exception for null state pointer.
|
||||
//***************************************************************************
|
||||
class fsm_null_state_exception : public etl::fsm_exception
|
||||
{
|
||||
public:
|
||||
|
||||
fsm_null_state_exception(string_type file_name, numeric_type line_number)
|
||||
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:null state", ETL_FILE"A"), file_name, line_number)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Exception for invalid state id.
|
||||
//***************************************************************************
|
||||
class fsm_state_id_exception : public etl::fsm_exception
|
||||
{
|
||||
public:
|
||||
|
||||
fsm_state_id_exception(string_type file_name, numeric_type line_number)
|
||||
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:state id", ETL_FILE"B"), file_name, line_number)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Exception for incompatible state list.
|
||||
//***************************************************************************
|
||||
class fsm_state_list_exception : public etl::fsm_exception
|
||||
{
|
||||
public:
|
||||
|
||||
fsm_state_list_exception(string_type file_name, numeric_type line_number)
|
||||
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:state list", ETL_FILE"C"), file_name, line_number)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Interface class for FSM states.
|
||||
//***************************************************************************
|
||||
class ifsm_state
|
||||
{
|
||||
public:
|
||||
|
||||
friend class fsm;
|
||||
|
||||
//*******************************************
|
||||
/// Gets the id for this state.
|
||||
//*******************************************
|
||||
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.
|
||||
//*******************************************
|
||||
ifsm_state(etl::fsm_state_id_t state_id_)
|
||||
: state_id(state_id_)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// Disabled.
|
||||
ifsm_state(const ifsm_state&);
|
||||
ifsm_state& operator =(const ifsm_state&);
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
class fsm : public etl::imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
//*******************************************
|
||||
/// Constructor.
|
||||
//*******************************************
|
||||
fsm()
|
||||
: p_state(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Set the states for the FSM
|
||||
//*******************************************
|
||||
template <typename TSize>
|
||||
void set_states(etl::ifsm_state** p_states, TSize size)
|
||||
{
|
||||
state_list = p_states;
|
||||
number_of_states = etl::fsm_state_id_t(size);
|
||||
|
||||
for (etl::fsm_state_id_t i = 0; i < size; ++i)
|
||||
{
|
||||
ETL_ASSERT((state_list[i] != nullptr), ETL_ERROR(etl::fsm_null_state_exception));
|
||||
}
|
||||
|
||||
bool ok = (number_of_states > 0) &&
|
||||
etl::is_sorted(state_list, state_list + number_of_states, fsm::CompareStateId());
|
||||
|
||||
ETL_ASSERT(ok, ETL_ERROR(etl::fsm_state_list_exception));
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Starts the FSM.
|
||||
/// Can only be called once.
|
||||
/// Subsequent calls will do nothing.
|
||||
//*******************************************
|
||||
void start()
|
||||
{
|
||||
// Can only be started once.
|
||||
if (p_state == nullptr)
|
||||
{
|
||||
p_state = state_list[0];
|
||||
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
|
||||
p_state->on_enter_state();
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Top level message handlers for the FSM.
|
||||
//*******************************************
|
||||
void receive(const etl::imessage& message)
|
||||
{
|
||||
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_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 = state_list[next_state_id];
|
||||
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
|
||||
p_state->on_enter_state();
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Gets the current state id.
|
||||
//*******************************************
|
||||
etl::fsm_state_id_t get_state_id() const
|
||||
{
|
||||
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
return p_state->get_state_id();
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Gets a reference to the current state interface.
|
||||
//*******************************************
|
||||
ifsm_state& get_state()
|
||||
{
|
||||
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
return *p_state;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Gets a const reference to the current state interface.
|
||||
//*******************************************
|
||||
const ifsm_state& get_state() const
|
||||
{
|
||||
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
return *p_state;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Checks if the FSM has been started.
|
||||
//*******************************************
|
||||
bool is_started() const
|
||||
{
|
||||
return p_state != nullptr;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Reset the FSM to pre-started state.
|
||||
//*******************************************
|
||||
void reset()
|
||||
{
|
||||
p_state = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct CompareStateId
|
||||
{
|
||||
bool operator()(etl::ifsm_state* lhs, etl::ifsm_state* rhs)
|
||||
{
|
||||
return lhs->get_state_id() < rhs->get_state_id();
|
||||
}
|
||||
};
|
||||
|
||||
etl::ifsm_state* p_state; ///< A pointer to the current state.
|
||||
etl::ifsm_state** state_list; ///< The list of added states.
|
||||
etl::fsm_state_id_t number_of_states; ///< The number of states.
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// To generate to header file, run this at the command line.
|
||||
// Note: You will need Python and COG installed.
|
||||
//
|
||||
// python -m cogapp -d -e -ofsm.h -DHandlers=<n> fsm_generator.h
|
||||
// Where <n> is the number of messages to support.
|
||||
//
|
||||
// e.g.
|
||||
// To generate handlers for up to 16 events...
|
||||
// python -m cogapp -d -e -ofsm.h -DHandlers=16 fsm_generator.h
|
||||
//
|
||||
// See CreateFSM.bat
|
||||
//***************************************************************************
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// The code below has been auto generated. Do not manually edit.")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("")
|
||||
################################################
|
||||
# The first definition for all of the events.
|
||||
################################################
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// The definition for all %s message types." % Handlers)
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename TState, const etl::fsm_state_id_t STATE_ID_, ")
|
||||
cog.out(" ")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("typename T%s = void, " % n)
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%s = void>" % Handlers)
|
||||
cog.outl("class fsm_state : public ifsm_state")
|
||||
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_")
|
||||
cog.outl(" };")
|
||||
cog.outl("")
|
||||
cog.outl(" fsm_state()")
|
||||
cog.outl(" : ifsm_state(STATE_ID)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
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("")
|
||||
cog.outl(" switch (event_id)")
|
||||
cog.outl(" {")
|
||||
for n in range(1, int(Handlers) + 1):
|
||||
cog.out(" case T%d::ID:" % n)
|
||||
cog.out(" new_state_id = static_cast<TState*>(this)->on_event(source, static_cast<const T%d&>(message));" % n)
|
||||
cog.outl(" break;")
|
||||
cog.out(" default:")
|
||||
cog.out(" new_state_id = static_cast<TState*>(this)->on_event_unknown(source, message);")
|
||||
cog.outl(" break;")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" return new_state_id;")
|
||||
cog.outl(" }")
|
||||
cog.outl("};")
|
||||
|
||||
####################################
|
||||
# All of the other specialisations.
|
||||
####################################
|
||||
for n in range(int(Handlers) - 1, 0, -1):
|
||||
cog.outl("")
|
||||
cog.outl("//***************************************************************************")
|
||||
if n == 1:
|
||||
cog.outl("// Specialisation for %d message type." % n)
|
||||
else:
|
||||
cog.outl("// Specialisation for %d message types." % n)
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename TState, const etl::fsm_state_id_t STATE_ID_, ")
|
||||
cog.out(" ")
|
||||
for t in range(1, n):
|
||||
cog.out("typename T%d, " % t)
|
||||
if t % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%d>" % n)
|
||||
cog.out("class fsm_state<TState, STATE_ID_, ")
|
||||
for t in range(1, n + 1):
|
||||
cog.out("T%d, " % t)
|
||||
if t % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
for t in range(n + 1, int(Handlers)):
|
||||
cog.out("void, ")
|
||||
if t % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
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(" {")
|
||||
cog.outl(" STATE_ID = STATE_ID_")
|
||||
cog.outl(" };")
|
||||
cog.outl("")
|
||||
cog.outl(" fsm_state()")
|
||||
cog.outl(" : ifsm_state(STATE_ID)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
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("")
|
||||
cog.outl(" switch (event_id)")
|
||||
cog.outl(" {")
|
||||
for n in range(1, n + 1):
|
||||
cog.out(" case T%d::ID:" % n)
|
||||
cog.out(" new_state_id = static_cast<TState*>(this)->on_event(source, static_cast<const T%d&>(message));" % n)
|
||||
cog.outl(" break;")
|
||||
cog.out(" default:")
|
||||
cog.out(" new_state_id = static_cast<TState*>(this)->on_event_unknown(source, message);")
|
||||
cog.outl(" break;")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" return new_state_id;")
|
||||
cog.outl(" }")
|
||||
cog.outl("};")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
}
|
||||
|
||||
#undef ETL_FILE
|
||||
|
||||
#endif
|
||||
715
src/message_router.h
Normal file
715
src/message_router.h
Normal file
@ -0,0 +1,715 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
http://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2017 jwellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __ETL_MESSAGE_ROUTER__
|
||||
#define __ETL_MESSAGE_ROUTER__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
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;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <const size_t ID_>
|
||||
class message : public imessage
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
ID = ID_
|
||||
};
|
||||
|
||||
id_t get_message_id() const
|
||||
{
|
||||
return id_t(ID);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
class imessage_router
|
||||
{
|
||||
public:
|
||||
virtual ~imessage_router() {}
|
||||
virtual void receive(const imessage& message) = 0;
|
||||
virtual void receive(imessage_router& source, const imessage& message) = 0;
|
||||
|
||||
void send_message(imessage_router& destination,
|
||||
const imessage& message)
|
||||
{
|
||||
destination.receive(*this, message);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// This router can be used either as a sink for messages
|
||||
/// or as a producer-only of messages such an interrupt routine.
|
||||
//***************************************************************************
|
||||
class null_message_router : public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& message)
|
||||
{
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& message)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// 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)
|
||||
{
|
||||
destination.receive(message);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Send a message to a router.
|
||||
//***************************************************************************
|
||||
inline static void send_message(imessage_router& source,
|
||||
imessage_router& destination,
|
||||
const imessage& message)
|
||||
{
|
||||
destination.receive(source, message);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
// To generate to header file, run this at the command line.
|
||||
// Note: You will need Python and COG installed.
|
||||
//
|
||||
// python -m cogapp -d -e -omessage_router.h -DHandlers=<n> message_router_generator.h
|
||||
// Where <n> is the number of messages to support.
|
||||
//
|
||||
// e.g.
|
||||
// To generate handlers for up to 16 messages...
|
||||
// python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h
|
||||
//
|
||||
// See CreateMessageProcessor.bat
|
||||
//***************************************************************************
|
||||
|
||||
//***************************************************************************
|
||||
// The code below has been auto generated. Do not manually edit.
|
||||
//***************************************************************************
|
||||
|
||||
//***************************************************************************
|
||||
// The definition for all 16 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
|
||||
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
|
||||
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
|
||||
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
|
||||
class message_router : public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const id_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
|
||||
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
|
||||
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
|
||||
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
|
||||
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
|
||||
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
|
||||
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
|
||||
case T11::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
|
||||
case T12::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
|
||||
case T13::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T13&>(msg)); break;
|
||||
case T14::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T14&>(msg)); break;
|
||||
case T15::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T15&>(msg)); break;
|
||||
case T16::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T16&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 15 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11, typename T12,
|
||||
typename T13, typename T14, typename T15>
|
||||
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
|
||||
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
|
||||
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
|
||||
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
|
||||
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
|
||||
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
|
||||
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
|
||||
case T11::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
|
||||
case T12::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
|
||||
case T13::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T13&>(msg)); break;
|
||||
case T14::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T14&>(msg)); break;
|
||||
case T15::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T15&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 14 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11, typename T12,
|
||||
typename T13, typename T14>
|
||||
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
|
||||
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
|
||||
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
|
||||
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
|
||||
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
|
||||
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
|
||||
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
|
||||
case T11::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
|
||||
case T12::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
|
||||
case T13::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T13&>(msg)); break;
|
||||
case T14::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T14&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 13 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11, typename T12,
|
||||
typename T13>
|
||||
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, void, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
|
||||
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
|
||||
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
|
||||
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
|
||||
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
|
||||
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
|
||||
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
|
||||
case T11::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
|
||||
case T12::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
|
||||
case T13::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T13&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 12 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11, typename T12>
|
||||
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, void, void, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
|
||||
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
|
||||
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
|
||||
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
|
||||
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
|
||||
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
|
||||
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
|
||||
case T11::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
|
||||
case T12::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 11 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10, typename T11>
|
||||
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, void, void, void, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
|
||||
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
|
||||
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
|
||||
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
|
||||
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
|
||||
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
|
||||
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
|
||||
case T11::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 10 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9, typename T10>
|
||||
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, void, void, void, void, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
|
||||
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
|
||||
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
|
||||
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
|
||||
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
|
||||
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
|
||||
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 9 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8,
|
||||
typename T9>
|
||||
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, void, void, void, void, void, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
|
||||
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
|
||||
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
|
||||
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
|
||||
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
|
||||
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 8 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8>
|
||||
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, void, void, void, void, void, void, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
|
||||
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
|
||||
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
|
||||
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
|
||||
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 7 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7>
|
||||
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, void, void, void, void, void, void, void, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
|
||||
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
|
||||
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
|
||||
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 6 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6>
|
||||
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, void, void, void, void, void, void, void, void, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
|
||||
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
|
||||
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 5 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5>
|
||||
class message_router<TProcessor, T1, T2, T3, T4, T5, void, void, void, void, void, void, void, void, void, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
|
||||
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 4 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2, typename T3, typename T4>
|
||||
class message_router<TProcessor, T1, T2, T3, T4, void, void, void, void, void, void, void, void, void, void, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 3 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2, typename T3>
|
||||
class message_router<TProcessor, T1, T2, T3, void, void, void, void, void, void, void, void, void, void, void, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 2 message types.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1, typename T2>
|
||||
class message_router<TProcessor, T1, T2, void, void, void, void, void, void, void, void, void, void, void, void, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for 1 message type.
|
||||
//***************************************************************************
|
||||
template <typename TProcessor,
|
||||
typename T1>
|
||||
class message_router<TProcessor, T1, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void>
|
||||
: public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& msg)
|
||||
{
|
||||
receive(etl::null_message_router(), msg);
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& msg)
|
||||
{
|
||||
const size_t id = msg.get_message_id();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
|
||||
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
243
src/message_router_generator.h
Normal file
243
src/message_router_generator.h
Normal file
@ -0,0 +1,243 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
http://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2017 jwellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __ETL_MESSAGE_ROUTER__
|
||||
#define __ETL_MESSAGE_ROUTER__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
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;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <const size_t ID_>
|
||||
class message : public imessage
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
ID = ID_
|
||||
};
|
||||
|
||||
id_t get_message_id() const
|
||||
{
|
||||
return id_t(ID);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
class imessage_router
|
||||
{
|
||||
public:
|
||||
virtual ~imessage_router() {}
|
||||
virtual void receive(const imessage& message) = 0;
|
||||
virtual void receive(imessage_router& source, const imessage& message) = 0;
|
||||
|
||||
void send_message(imessage_router& destination,
|
||||
const imessage& message)
|
||||
{
|
||||
destination.receive(*this, message);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// This router can be used either as a sink for messages
|
||||
/// or as a producer-only of messages such an interrupt routine.
|
||||
//***************************************************************************
|
||||
class null_message_router : public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
void receive(const imessage& message)
|
||||
{
|
||||
}
|
||||
|
||||
void receive(imessage_router& source, const imessage& message)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// 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)
|
||||
{
|
||||
destination.receive(message);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Send a message to a router.
|
||||
//***************************************************************************
|
||||
inline static void send_message(imessage_router& source,
|
||||
imessage_router& destination,
|
||||
const imessage& message)
|
||||
{
|
||||
destination.receive(source, message);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
// To generate to header file, run this at the command line.
|
||||
// Note: You will need Python and COG installed.
|
||||
//
|
||||
// python -m cogapp -d -e -omessage_router.h -DHandlers=<n> message_router_generator.h
|
||||
// Where <n> is the number of messages to support.
|
||||
//
|
||||
// e.g.
|
||||
// To generate handlers for up to 16 messages...
|
||||
// python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h
|
||||
//
|
||||
// See CreateMessageProcessor.bat
|
||||
//***************************************************************************
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// The code below has been auto generated. Do not manually edit.")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("")
|
||||
################################################
|
||||
# The first definition for all of the messages.
|
||||
################################################
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// The definition for all %s message types." % Handlers)
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename TProcessor,")
|
||||
cog.out(" ")
|
||||
cog.out("typename T1, ")
|
||||
for n in range(2, int(Handlers)):
|
||||
cog.out("typename T%s = void, " % n)
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%s = void>" % Handlers)
|
||||
cog.out("class message_router")
|
||||
cog.outl(" : public imessage_router")
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
cog.outl("")
|
||||
cog.outl(" void receive(const 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(" {")
|
||||
cog.outl(" const id_t id = msg.get_message_id();")
|
||||
cog.outl("")
|
||||
cog.outl(" switch (id)")
|
||||
cog.outl(" {")
|
||||
for n in range(1, int(Handlers) + 1):
|
||||
cog.out(" case T%d::ID:" % n)
|
||||
cog.out(" static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T%d&>(msg));" % n)
|
||||
cog.outl(" break;")
|
||||
cog.out(" default:")
|
||||
cog.out(" static_cast<TProcessor*>(this)->on_receive_unknown(source, msg);")
|
||||
cog.outl(" break;")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl("};")
|
||||
|
||||
####################################
|
||||
# All of the other specialisations.
|
||||
####################################
|
||||
for n in range(int(Handlers) - 1, 0, -1):
|
||||
cog.outl("")
|
||||
cog.outl("//***************************************************************************")
|
||||
if n == 1:
|
||||
cog.outl("// Specialisation for %d message type." % n)
|
||||
else:
|
||||
cog.outl("// Specialisation for %d message types." % n)
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename TProcessor, ")
|
||||
cog.out(" ")
|
||||
for t in range(1, n):
|
||||
cog.out("typename T%d, " % t)
|
||||
if t % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%d>" % n)
|
||||
cog.out("class message_router<TProcessor, ")
|
||||
for t in range(1, n + 1):
|
||||
cog.out("T%d, " % t)
|
||||
if t % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
for t in range(n + 1, int(Handlers)):
|
||||
cog.out("void, ")
|
||||
if t % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("void>")
|
||||
cog.outl(" : public imessage_router")
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
cog.outl("")
|
||||
cog.outl(" void receive(const 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(" {")
|
||||
cog.outl(" const size_t id = msg.get_message_id();")
|
||||
cog.outl("")
|
||||
cog.outl(" switch (id)")
|
||||
cog.outl(" {")
|
||||
for t in range(1, n + 1):
|
||||
cog.out(" case T%d::ID:" % t)
|
||||
cog.out(" static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T%d&>(msg));" % t)
|
||||
cog.outl(" break;")
|
||||
cog.out(" default:")
|
||||
cog.out(" static_cast<TProcessor*>(this)->on_receive_unknown(source, msg);")
|
||||
cog.outl(" break;")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl("};")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
}
|
||||
|
||||
#endif
|
||||
498
test/test_fsm.cpp
Normal file
498
test/test_fsm.cpp
Normal file
@ -0,0 +1,498 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2017 jwellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "UnitTest++.h"
|
||||
|
||||
#include "fsm.h"
|
||||
#include "enum_type.h"
|
||||
#include "container.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace
|
||||
{
|
||||
//***************************************************************************
|
||||
// Events
|
||||
struct EventId
|
||||
{
|
||||
enum enum_type
|
||||
{
|
||||
START,
|
||||
STOP,
|
||||
STOPPED,
|
||||
SET_SPEED
|
||||
};
|
||||
|
||||
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_END_ENUM_TYPE
|
||||
};
|
||||
|
||||
//***********************************
|
||||
class Start : public etl::message<EventId::START>
|
||||
{
|
||||
};
|
||||
|
||||
//***********************************
|
||||
class Stop : public etl::message<EventId::STOP>
|
||||
{
|
||||
public:
|
||||
|
||||
Stop() : isEmergencyStop(false) {}
|
||||
Stop(bool emergency) : isEmergencyStop(emergency) {}
|
||||
|
||||
const bool isEmergencyStop;
|
||||
};
|
||||
|
||||
//***********************************
|
||||
class SetSpeed : public etl::message<EventId::SET_SPEED>
|
||||
{
|
||||
public:
|
||||
|
||||
SetSpeed(int speed) : speed(speed) {}
|
||||
|
||||
const int speed;
|
||||
};
|
||||
|
||||
//***********************************
|
||||
class Stopped : public etl::message<EventId::STOPPED>
|
||||
{
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// States
|
||||
struct StateId
|
||||
{
|
||||
enum enum_type
|
||||
{
|
||||
IDLE,
|
||||
RUNNING,
|
||||
WINDING_DOWN,
|
||||
NUMBER_OF_STATES
|
||||
};
|
||||
|
||||
ETL_DECLARE_ENUM_TYPE(StateId, etl::fsm_state_id_t)
|
||||
ETL_ENUM_TYPE(IDLE, "Idle")
|
||||
ETL_ENUM_TYPE(RUNNING, "Running")
|
||||
ETL_ENUM_TYPE(WINDING_DOWN, "Winding Down")
|
||||
ETL_END_ENUM_TYPE
|
||||
};
|
||||
|
||||
class MotorControl;
|
||||
|
||||
//***********************************
|
||||
// Common functionality
|
||||
//***********************************
|
||||
class Common
|
||||
{
|
||||
public:
|
||||
|
||||
//***********************************
|
||||
Common()
|
||||
{
|
||||
ClearStatistics();
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void ClearStatistics()
|
||||
{
|
||||
startCount = 0;
|
||||
stopCount = 0;
|
||||
setSpeedCount = 0;
|
||||
unknownCount = 0;
|
||||
stoppedCount = 0;
|
||||
isLampOn = false;
|
||||
speed = 0;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void SetSpeed(int speed_)
|
||||
{
|
||||
speed = speed_;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void TurnRunningLampOn()
|
||||
{
|
||||
isLampOn = true;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void TurnRunningLampOff()
|
||||
{
|
||||
isLampOn = false;
|
||||
}
|
||||
|
||||
int startCount;
|
||||
int stopCount;
|
||||
int setSpeedCount;
|
||||
int unknownCount;
|
||||
int stoppedCount;
|
||||
bool isLampOn;
|
||||
int speed;
|
||||
};
|
||||
|
||||
//***********************************
|
||||
// The idle state.
|
||||
//***********************************
|
||||
class Idle : public etl::fsm_state<Idle, StateId::IDLE, Start>
|
||||
{
|
||||
public:
|
||||
|
||||
//***********************************
|
||||
Idle(Common& common)
|
||||
: common(common)
|
||||
{
|
||||
}
|
||||
|
||||
//***********************************
|
||||
etl::fsm_state_id_t on_event(etl::imessage_router& sender, const Start& event)
|
||||
{
|
||||
++common.startCount;
|
||||
return StateId::RUNNING;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
etl::fsm_state_id_t on_event_unknown(etl::imessage_router& sender, const etl::imessage& event)
|
||||
{
|
||||
++common.unknownCount;
|
||||
return STATE_ID;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void on_enter_state()
|
||||
{
|
||||
common.TurnRunningLampOff();
|
||||
}
|
||||
|
||||
Common& common;
|
||||
};
|
||||
|
||||
//***********************************
|
||||
// The running state.
|
||||
//***********************************
|
||||
class Running : public etl::fsm_state<Running, StateId::RUNNING, Stop, SetSpeed>
|
||||
{
|
||||
public:
|
||||
|
||||
//***********************************
|
||||
Running(Common& common)
|
||||
: common(common)
|
||||
{
|
||||
}
|
||||
|
||||
//***********************************
|
||||
etl::fsm_state_id_t on_event(etl::imessage_router& sender, const Stop& event)
|
||||
{
|
||||
++common.stopCount;
|
||||
|
||||
if (event.isEmergencyStop)
|
||||
{
|
||||
return StateId::IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return StateId::WINDING_DOWN;
|
||||
}
|
||||
}
|
||||
|
||||
//***********************************
|
||||
etl::fsm_state_id_t on_event(etl::imessage_router& sender, const SetSpeed& event)
|
||||
{
|
||||
++common.setSpeedCount;
|
||||
common.SetSpeed(event.speed);
|
||||
return STATE_ID;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
etl::fsm_state_id_t on_event_unknown(etl::imessage_router& sender, const etl::imessage& event)
|
||||
{
|
||||
++common.unknownCount;
|
||||
return STATE_ID;
|
||||
}
|
||||
|
||||
void on_enter_state()
|
||||
{
|
||||
common.TurnRunningLampOn();
|
||||
}
|
||||
|
||||
Common& common;
|
||||
};
|
||||
|
||||
//***********************************
|
||||
// The winding down state.
|
||||
//***********************************
|
||||
class WindingDown : public etl::fsm_state<WindingDown, StateId::WINDING_DOWN, Stopped>
|
||||
{
|
||||
public:
|
||||
|
||||
//***********************************
|
||||
WindingDown(Common& common)
|
||||
: common(common)
|
||||
{
|
||||
}
|
||||
|
||||
//***********************************
|
||||
etl::fsm_state_id_t on_event(etl::imessage_router& source, const Stopped& event)
|
||||
{
|
||||
++common.stoppedCount;
|
||||
return StateId::IDLE;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
etl::fsm_state_id_t on_event_unknown(etl::imessage_router& source, const etl::imessage& event)
|
||||
{
|
||||
++common.unknownCount;
|
||||
return STATE_ID;
|
||||
}
|
||||
|
||||
Common& common;
|
||||
};
|
||||
|
||||
//***********************************
|
||||
// The motor control FSM.
|
||||
//***********************************
|
||||
class MotorControl : public etl::fsm
|
||||
{
|
||||
public:
|
||||
|
||||
MotorControl()
|
||||
: idle(common),
|
||||
running(common),
|
||||
windingDown(common)
|
||||
{
|
||||
set_states(stateList, etl::size(stateList));
|
||||
}
|
||||
|
||||
Common common;
|
||||
|
||||
private:
|
||||
|
||||
// The states.
|
||||
Idle idle;
|
||||
Running running;
|
||||
WindingDown windingDown;
|
||||
|
||||
etl::ifsm_state* stateList[StateId::NUMBER_OF_STATES] =
|
||||
{
|
||||
&idle, &running, &windingDown
|
||||
};
|
||||
};
|
||||
|
||||
MotorControl motorControl;
|
||||
|
||||
SUITE(test_map)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST(test_fsm)
|
||||
{
|
||||
motorControl.reset();
|
||||
motorControl.common.ClearStatistics();
|
||||
|
||||
CHECK(!motorControl.is_started());
|
||||
|
||||
// Start the FSM.
|
||||
motorControl.start();
|
||||
CHECK(motorControl.is_started());
|
||||
|
||||
// Now in Idle state.
|
||||
|
||||
CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id()));
|
||||
CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state().get_state_id()));
|
||||
|
||||
CHECK_EQUAL(false, motorControl.common.isLampOn);
|
||||
CHECK_EQUAL(0, motorControl.common.setSpeedCount);
|
||||
CHECK_EQUAL(0, motorControl.common.speed);
|
||||
CHECK_EQUAL(0, motorControl.common.startCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stoppedCount);
|
||||
CHECK_EQUAL(0, motorControl.common.unknownCount);
|
||||
|
||||
// Send unhandled events.
|
||||
motorControl.receive(etl::null_message_router(), Stop());
|
||||
motorControl.receive(etl::null_message_router(), Stopped());
|
||||
motorControl.receive(etl::null_message_router(), SetSpeed(10));
|
||||
|
||||
CHECK_EQUAL(StateId::IDLE, motorControl.get_state_id());
|
||||
CHECK_EQUAL(StateId::IDLE, motorControl.get_state().get_state_id());
|
||||
|
||||
CHECK_EQUAL(false, motorControl.common.isLampOn);
|
||||
CHECK_EQUAL(0, motorControl.common.setSpeedCount);
|
||||
CHECK_EQUAL(0, motorControl.common.speed);
|
||||
CHECK_EQUAL(0, motorControl.common.startCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stoppedCount);
|
||||
CHECK_EQUAL(3, motorControl.common.unknownCount);
|
||||
|
||||
// Send Start event.
|
||||
motorControl.receive(etl::null_message_router(), Start());
|
||||
|
||||
// Now in Running state.
|
||||
|
||||
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id()));
|
||||
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state().get_state_id()));
|
||||
|
||||
CHECK_EQUAL(true, motorControl.common.isLampOn);
|
||||
CHECK_EQUAL(0, motorControl.common.setSpeedCount);
|
||||
CHECK_EQUAL(0, motorControl.common.speed);
|
||||
CHECK_EQUAL(1, motorControl.common.startCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stoppedCount);
|
||||
CHECK_EQUAL(3, motorControl.common.unknownCount);
|
||||
|
||||
// Send unhandled events.
|
||||
motorControl.receive(etl::null_message_router(), Start());
|
||||
motorControl.receive(etl::null_message_router(), Stopped());
|
||||
|
||||
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id()));
|
||||
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state().get_state_id()));
|
||||
|
||||
CHECK_EQUAL(true, motorControl.common.isLampOn);
|
||||
CHECK_EQUAL(0, motorControl.common.setSpeedCount);
|
||||
CHECK_EQUAL(0, motorControl.common.speed);
|
||||
CHECK_EQUAL(1, motorControl.common.startCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stoppedCount);
|
||||
CHECK_EQUAL(5, motorControl.common.unknownCount);
|
||||
|
||||
// Send SetSpeed event.
|
||||
motorControl.receive(etl::null_message_router(), SetSpeed(100));
|
||||
|
||||
// Still in Running state.
|
||||
|
||||
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id()));
|
||||
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state().get_state_id()));
|
||||
|
||||
CHECK_EQUAL(true, motorControl.common.isLampOn);
|
||||
CHECK_EQUAL(1, motorControl.common.setSpeedCount);
|
||||
CHECK_EQUAL(100, motorControl.common.speed);
|
||||
CHECK_EQUAL(1, motorControl.common.startCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stoppedCount);
|
||||
CHECK_EQUAL(5, motorControl.common.unknownCount);
|
||||
|
||||
// Send Stop event.
|
||||
motorControl.receive(etl::null_message_router(), Stop());
|
||||
|
||||
// Now in WindingDown state.
|
||||
|
||||
CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControl.get_state_id()));
|
||||
CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControl.get_state().get_state_id()));
|
||||
|
||||
CHECK_EQUAL(true, motorControl.common.isLampOn);
|
||||
CHECK_EQUAL(1, motorControl.common.setSpeedCount);
|
||||
CHECK_EQUAL(100, motorControl.common.speed);
|
||||
CHECK_EQUAL(1, motorControl.common.startCount);
|
||||
CHECK_EQUAL(1, motorControl.common.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stoppedCount);
|
||||
CHECK_EQUAL(5, motorControl.common.unknownCount);
|
||||
|
||||
// Send unhandled events.
|
||||
motorControl.receive(etl::null_message_router(), Start());
|
||||
motorControl.receive(etl::null_message_router(), Stop());
|
||||
motorControl.receive(etl::null_message_router(), SetSpeed(100));
|
||||
|
||||
CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControl.get_state_id()));
|
||||
CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControl.get_state().get_state_id()));
|
||||
|
||||
CHECK_EQUAL(true, motorControl.common.isLampOn);
|
||||
CHECK_EQUAL(1, motorControl.common.setSpeedCount);
|
||||
CHECK_EQUAL(100, motorControl.common.speed);
|
||||
CHECK_EQUAL(1, motorControl.common.startCount);
|
||||
CHECK_EQUAL(1, motorControl.common.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stoppedCount);
|
||||
CHECK_EQUAL(8, motorControl.common.unknownCount);
|
||||
|
||||
// Send Stopped event.
|
||||
motorControl.receive(etl::null_message_router(), Stopped());
|
||||
|
||||
// Now in Idle state.
|
||||
|
||||
CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id()));
|
||||
CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state().get_state_id()));
|
||||
|
||||
CHECK_EQUAL(false, motorControl.common.isLampOn);
|
||||
CHECK_EQUAL(1, motorControl.common.setSpeedCount);
|
||||
CHECK_EQUAL(100, motorControl.common.speed);
|
||||
CHECK_EQUAL(1, motorControl.common.startCount);
|
||||
CHECK_EQUAL(1, motorControl.common.stopCount);
|
||||
CHECK_EQUAL(1, motorControl.common.stoppedCount);
|
||||
CHECK_EQUAL(8, motorControl.common.unknownCount);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_fsm_emergency_stop)
|
||||
{
|
||||
motorControl.reset();
|
||||
motorControl.common.ClearStatistics();
|
||||
|
||||
CHECK(!motorControl.is_started());
|
||||
|
||||
// Start the FSM.
|
||||
motorControl.start();
|
||||
CHECK(motorControl.is_started());
|
||||
|
||||
// Now in Idle state.
|
||||
|
||||
// Send Start event.
|
||||
motorControl.receive(etl::null_message_router(), Start());
|
||||
|
||||
// Now in Running state.
|
||||
|
||||
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id()));
|
||||
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state().get_state_id()));
|
||||
|
||||
CHECK_EQUAL(true, motorControl.common.isLampOn);
|
||||
CHECK_EQUAL(0, motorControl.common.setSpeedCount);
|
||||
CHECK_EQUAL(0, motorControl.common.speed);
|
||||
CHECK_EQUAL(1, motorControl.common.startCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stoppedCount);
|
||||
CHECK_EQUAL(0, motorControl.common.unknownCount);
|
||||
|
||||
// Send emergency Stop event.
|
||||
motorControl.receive(etl::null_message_router(), Stop(true));
|
||||
|
||||
// Now in Idle state.
|
||||
|
||||
CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id()));
|
||||
CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state().get_state_id()));
|
||||
|
||||
CHECK_EQUAL(false, motorControl.common.isLampOn);
|
||||
CHECK_EQUAL(0, motorControl.common.setSpeedCount);
|
||||
CHECK_EQUAL(0, motorControl.common.speed);
|
||||
CHECK_EQUAL(1, motorControl.common.startCount);
|
||||
CHECK_EQUAL(1, motorControl.common.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.common.stoppedCount);
|
||||
CHECK_EQUAL(0, motorControl.common.unknownCount);
|
||||
}
|
||||
};
|
||||
}
|
||||
325
test/test_message_router.cpp
Normal file
325
test/test_message_router.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
http://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2017 jwellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "UnitTest++.h"
|
||||
#include "ExtraCheckMacros.h"
|
||||
|
||||
#include "message_router.h"
|
||||
|
||||
//***************************************************************************
|
||||
// The set of messages.
|
||||
//***************************************************************************
|
||||
namespace
|
||||
{
|
||||
enum
|
||||
{
|
||||
MESSAGE1,
|
||||
MESSAGE2,
|
||||
MESSAGE3,
|
||||
MESSAGE4,
|
||||
MESSAGE5
|
||||
};
|
||||
|
||||
struct Message1 : public etl::message<MESSAGE1>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
struct Message2 : public etl::message<MESSAGE2>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
struct Message3 : public etl::message<MESSAGE3>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
struct Message4 : public etl::message<MESSAGE4>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
struct Message5 : public etl::message<MESSAGE5>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
Message1 message1;
|
||||
Message2 message2;
|
||||
Message3 message3;
|
||||
Message4 message4;
|
||||
Message5 message5;
|
||||
|
||||
//***************************************************************************
|
||||
// Router that handles messages 1, 2, 3, 4 and 5 and returns nothing.
|
||||
//***************************************************************************
|
||||
class Router1 : public etl::message_router<Router1, Message1, Message2, Message3, Message4, Message5>
|
||||
{
|
||||
public:
|
||||
|
||||
Router1()
|
||||
: message1_count(0),
|
||||
message2_count(0),
|
||||
message3_count(0),
|
||||
message4_count(0),
|
||||
message_unknown_count(0),
|
||||
callback_count(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& sender, const Message1& msg)
|
||||
{
|
||||
++message1_count;
|
||||
etl::send_message(sender, message5);
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& sender, const Message2& msg)
|
||||
{
|
||||
++message2_count;
|
||||
etl::send_message(sender, message5);
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& sender, const Message3& msg)
|
||||
{
|
||||
++message3_count;
|
||||
etl::send_message(sender, message5);
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& sender, const Message4& msg)
|
||||
{
|
||||
++message4_count;
|
||||
etl::send_message(sender, message5);
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& sender, const Message5& msg)
|
||||
{
|
||||
++callback_count;
|
||||
}
|
||||
|
||||
void on_receive_unknown(etl::imessage_router& sender, const etl::imessage& msg)
|
||||
{
|
||||
++message_unknown_count;
|
||||
}
|
||||
|
||||
int message1_count;
|
||||
int message2_count;
|
||||
int message3_count;
|
||||
int message4_count;
|
||||
int message_unknown_count;
|
||||
int callback_count;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Router that handles messages 1, 2, 4 and 5 and returns nothing.
|
||||
//***************************************************************************
|
||||
class Router2 : public etl::message_router<Router2, Message1, Message2, Message4, Message5>
|
||||
{
|
||||
public:
|
||||
|
||||
Router2()
|
||||
: message1_count(0),
|
||||
message2_count(0),
|
||||
message4_count(0),
|
||||
message_unknown_count(0),
|
||||
callback_count(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& sender, const Message1& msg)
|
||||
{
|
||||
++message1_count;
|
||||
etl::send_message(sender, message5);
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& sender, const Message2& msg)
|
||||
{
|
||||
++message2_count;
|
||||
etl::send_message(sender, message5);
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& sender, const Message4& msg)
|
||||
{
|
||||
++message4_count;
|
||||
etl::send_message(sender, message5);
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& sender, const Message5& msg)
|
||||
{
|
||||
++callback_count;
|
||||
}
|
||||
|
||||
void on_receive_unknown(etl::imessage_router& sender, const etl::imessage& msg)
|
||||
{
|
||||
++message_unknown_count;
|
||||
etl::send_message(sender, message5);
|
||||
}
|
||||
|
||||
int message1_count;
|
||||
int message2_count;
|
||||
int message4_count;
|
||||
int message_unknown_count;
|
||||
int callback_count;
|
||||
};
|
||||
|
||||
|
||||
etl::imessage_router* p_router;
|
||||
|
||||
SUITE(test_message_router)
|
||||
{
|
||||
//=========================================================================
|
||||
TEST(message_router)
|
||||
{
|
||||
Router1 r1;
|
||||
Router2 r2;
|
||||
|
||||
p_router = &r1;
|
||||
|
||||
p_router->receive(r2, message1);
|
||||
CHECK_EQUAL(1, r1.message1_count);
|
||||
CHECK_EQUAL(0, r1.message2_count);
|
||||
CHECK_EQUAL(0, r1.message3_count);
|
||||
CHECK_EQUAL(0, r1.message4_count);
|
||||
CHECK_EQUAL(0, r1.message_unknown_count);
|
||||
CHECK_EQUAL(1, r2.callback_count);
|
||||
|
||||
p_router->receive(r2, message2);
|
||||
CHECK_EQUAL(1, r1.message1_count);
|
||||
CHECK_EQUAL(1, r1.message2_count);
|
||||
CHECK_EQUAL(0, r1.message3_count);
|
||||
CHECK_EQUAL(0, r1.message4_count);
|
||||
CHECK_EQUAL(0, r1.message_unknown_count);
|
||||
CHECK_EQUAL(2, r2.callback_count);
|
||||
|
||||
p_router->receive(r2, message3);
|
||||
CHECK_EQUAL(1, r1.message1_count);
|
||||
CHECK_EQUAL(1, r1.message2_count);
|
||||
CHECK_EQUAL(1, r1.message3_count);
|
||||
CHECK_EQUAL(0, r1.message4_count);
|
||||
CHECK_EQUAL(0, r1.message_unknown_count);
|
||||
CHECK_EQUAL(3, r2.callback_count);
|
||||
|
||||
p_router->receive(r2, message4);
|
||||
CHECK_EQUAL(1, r1.message1_count);
|
||||
CHECK_EQUAL(1, r1.message2_count);
|
||||
CHECK_EQUAL(1, r1.message3_count);
|
||||
CHECK_EQUAL(1, r1.message4_count);
|
||||
CHECK_EQUAL(0, r1.message_unknown_count);
|
||||
CHECK_EQUAL(4, r2.callback_count);
|
||||
|
||||
p_router = &r2;
|
||||
|
||||
p_router->receive(r1, message1);
|
||||
CHECK_EQUAL(1, r2.message1_count);
|
||||
CHECK_EQUAL(0, r2.message2_count);
|
||||
CHECK_EQUAL(0, r2.message4_count);
|
||||
CHECK_EQUAL(0, r2.message_unknown_count);
|
||||
CHECK_EQUAL(1, r1.callback_count);
|
||||
|
||||
p_router->receive(r1, message2);
|
||||
CHECK_EQUAL(1, r2.message1_count);
|
||||
CHECK_EQUAL(1, r2.message2_count);
|
||||
CHECK_EQUAL(0, r2.message4_count);
|
||||
CHECK_EQUAL(0, r2.message_unknown_count);
|
||||
CHECK_EQUAL(2, r1.callback_count);
|
||||
|
||||
p_router->receive(r1, message3);
|
||||
CHECK_EQUAL(1, r2.message1_count);
|
||||
CHECK_EQUAL(1, r2.message2_count);
|
||||
CHECK_EQUAL(0, r2.message4_count);
|
||||
CHECK_EQUAL(1, r2.message_unknown_count);
|
||||
CHECK_EQUAL(3, r1.callback_count);
|
||||
|
||||
p_router->receive(r1, message4);
|
||||
CHECK_EQUAL(1, r2.message1_count);
|
||||
CHECK_EQUAL(1, r2.message2_count);
|
||||
CHECK_EQUAL(1, r2.message4_count);
|
||||
CHECK_EQUAL(1, r2.message_unknown_count);
|
||||
CHECK_EQUAL(4, r1.callback_count);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
TEST(message_null_router)
|
||||
{
|
||||
Router2 router;
|
||||
etl::null_message_router null_router;
|
||||
|
||||
// Send from the null router.
|
||||
etl::send_message(router, message1);
|
||||
CHECK_EQUAL(1, router.message1_count);
|
||||
CHECK_EQUAL(0, router.message2_count);
|
||||
CHECK_EQUAL(0, router.message4_count);
|
||||
CHECK_EQUAL(0, router.message_unknown_count);
|
||||
|
||||
etl::send_message(router, message2);
|
||||
CHECK_EQUAL(1, router.message1_count);
|
||||
CHECK_EQUAL(1, router.message2_count);
|
||||
CHECK_EQUAL(0, router.message4_count);
|
||||
CHECK_EQUAL(0, router.message_unknown_count);
|
||||
|
||||
etl::send_message(router, message3);
|
||||
CHECK_EQUAL(1, router.message1_count);
|
||||
CHECK_EQUAL(1, router.message2_count);
|
||||
CHECK_EQUAL(0, router.message4_count);
|
||||
CHECK_EQUAL(1, router.message_unknown_count);
|
||||
|
||||
etl::send_message(router, message4);
|
||||
CHECK_EQUAL(1, router.message1_count);
|
||||
CHECK_EQUAL(1, router.message2_count);
|
||||
CHECK_EQUAL(1, router.message4_count);
|
||||
CHECK_EQUAL(1, router.message_unknown_count);
|
||||
|
||||
// Send to the null router.
|
||||
etl::send_message(null_router, message1);
|
||||
CHECK_EQUAL(1, router.message1_count);
|
||||
CHECK_EQUAL(1, router.message2_count);
|
||||
CHECK_EQUAL(1, router.message4_count);
|
||||
CHECK_EQUAL(1, router.message_unknown_count);
|
||||
|
||||
etl::send_message(null_router, message2);
|
||||
CHECK_EQUAL(1, router.message1_count);
|
||||
CHECK_EQUAL(1, router.message2_count);
|
||||
CHECK_EQUAL(1, router.message4_count);
|
||||
CHECK_EQUAL(1, router.message_unknown_count);
|
||||
|
||||
etl::send_message(null_router, message3);
|
||||
CHECK_EQUAL(1, router.message1_count);
|
||||
CHECK_EQUAL(1, router.message2_count);
|
||||
CHECK_EQUAL(1, router.message4_count);
|
||||
CHECK_EQUAL(1, router.message_unknown_count);
|
||||
|
||||
etl::send_message(null_router, message4);
|
||||
CHECK_EQUAL(1, router.message1_count);
|
||||
CHECK_EQUAL(1, router.message2_count);
|
||||
CHECK_EQUAL(1, router.message4_count);
|
||||
CHECK_EQUAL(1, router.message_unknown_count);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -216,7 +216,6 @@
|
||||
<ClInclude Include="..\..\src\flat_map.h" />
|
||||
<ClInclude Include="..\..\src\map.h" />
|
||||
<ClInclude Include="..\..\src\memory.h" />
|
||||
<ClInclude Include="..\..\src\mru_cache.h" />
|
||||
<ClInclude Include="..\..\src\multimap.h" />
|
||||
<ClInclude Include="..\..\src\multiset.h" />
|
||||
<ClInclude Include="..\..\src\multi_array.h" />
|
||||
@ -240,7 +239,6 @@
|
||||
<ClInclude Include="..\..\src\reference_flat_multimap.h" />
|
||||
<ClInclude Include="..\..\src\reference_flat_multiset.h" />
|
||||
<ClInclude Include="..\..\src\reference_flat_set.h" />
|
||||
<ClInclude Include="..\..\src\rr_cache.h" />
|
||||
<ClInclude Include="..\..\src\set.h" />
|
||||
<ClInclude Include="..\..\src\smallest.h" />
|
||||
<ClInclude Include="..\..\src\stack.h" />
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
<UniqueIdentifier>{7028012c-30c4-4993-b2d9-3b1521a610ae}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ETL\Frameworks">
|
||||
<UniqueIdentifier>{5de50c3d-4679-4eb3-9b76-e43e1aad6a66}</UniqueIdentifier>
|
||||
<UniqueIdentifier>{6be3bc76-e17c-4be0-8b0b-d1053e1a1761}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -261,12 +261,6 @@
|
||||
<ClInclude Include="..\..\src\icache.h">
|
||||
<Filter>ETL\Containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\mru_cache.h">
|
||||
<Filter>ETL\Containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rr_cache.h">
|
||||
<Filter>ETL\Containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\intrusive_links.h">
|
||||
<Filter>ETL\Containers</Filter>
|
||||
</ClInclude>
|
||||
@ -439,16 +433,16 @@
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\fsm.h">
|
||||
<Filter>ETL\Patterns</Filter>
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\fsm_generator.h">
|
||||
<Filter>ETL\Patterns</Filter>
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\message_router.h">
|
||||
<Filter>ETL\Patterns</Filter>
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\message_router_generator.h">
|
||||
<Filter>ETL\Patterns</Filter>
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -788,10 +782,10 @@
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="..\..\src\CreateFSM.bat">
|
||||
<Filter>ETL\Patterns</Filter>
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</None>
|
||||
<None Include="..\..\src\CreateMessageRouter.bat">
|
||||
<Filter>ETL\Patterns</Filter>
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user