1524 lines
59 KiB
C
1524 lines
59 KiB
C
|
/******************************************************************************
|
||
|
The MIT License(MIT)
|
||
|
|
||
|
Embedded Template Library.
|
||
|
https://github.com/ETLCPP/etl
|
||
|
https://www.etlcpp.com
|
||
|
|
||
|
Copyright(c) 2017 John Wellbelove
|
||
|
|
||
|
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.
|
||
|
******************************************************************************/
|
||
|
|
||
|
#if 0
|
||
|
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
|
||
|
#endif
|
||
|
|
||
|
//***************************************************************************
|
||
|
// THIS FILE HAS BEEN AUTO GENERATED. DO NOT EDIT THIS FILE.
|
||
|
//***************************************************************************
|
||
|
|
||
|
//***************************************************************************
|
||
|
// 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 generate.bat
|
||
|
//***************************************************************************
|
||
|
|
||
|
#ifndef ETL_FSM_INCLUDED
|
||
|
#define ETL_FSM_INCLUDED
|
||
|
|
||
|
#include "platform.h"
|
||
|
#include "array.h"
|
||
|
#include "nullptr.h"
|
||
|
#include "error_handler.h"
|
||
|
#include "exception.h"
|
||
|
#include "user_type.h"
|
||
|
#include "message_router.h"
|
||
|
#include "integral_limits.h"
|
||
|
#include "largest.h"
|
||
|
|
||
|
#include <stdint.h>
|
||
|
|
||
|
#include "private/minmax_push.h"
|
||
|
|
||
|
namespace etl
|
||
|
{
|
||
|
class fsm;
|
||
|
class hfsm;
|
||
|
|
||
|
/// 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
|
||
|
|
||
|
// For internal FSM use.
|
||
|
typedef typename etl::larger_type<etl::message_id_t>::type fsm_internal_id_t;
|
||
|
|
||
|
#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
|
||
|
template <typename, typename, etl::fsm_state_id_t, typename...>
|
||
|
class fsm_state;
|
||
|
#else
|
||
|
template <typename, typename, etl::fsm_state_id_t,
|
||
|
typename, typename, typename, typename,
|
||
|
typename, typename, typename, typename,
|
||
|
typename, typename, typename, typename,
|
||
|
typename, typename, typename, typename>
|
||
|
class fsm_state;
|
||
|
#endif
|
||
|
|
||
|
//***************************************************************************
|
||
|
/// Base exception class for FSM.
|
||
|
//***************************************************************************
|
||
|
class fsm_exception : public etl::exception
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
fsm_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
|
||
|
: etl::exception(reason_, 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_FSM_FILE_ID"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_FSM_FILE_ID"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_FSM_FILE_ID"C"), file_name_, line_number_)
|
||
|
{
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
/// Exception for incompatible order state list.
|
||
|
//***************************************************************************
|
||
|
class fsm_state_list_order_exception : public etl::fsm_exception
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
fsm_state_list_order_exception(string_type file_name_, numeric_type line_number_)
|
||
|
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:state list order", ETL_FSM_FILE_ID"D"), file_name_, line_number_)
|
||
|
{
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
/// Exception for forbidden state changes.
|
||
|
//***************************************************************************
|
||
|
class fsm_state_composite_state_change_forbidden : public etl::fsm_exception
|
||
|
{
|
||
|
public:
|
||
|
fsm_state_composite_state_change_forbidden(string_type file_name_, numeric_type line_number_)
|
||
|
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:change in composite state forbidden", ETL_FSM_FILE_ID"E"), file_name_, line_number_)
|
||
|
{
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
/// Exception for message received but not started.
|
||
|
//***************************************************************************
|
||
|
class fsm_not_started : public etl::fsm_exception
|
||
|
{
|
||
|
public:
|
||
|
fsm_not_started(string_type file_name_, numeric_type line_number_)
|
||
|
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:not started", ETL_FSM_FILE_ID"F"), file_name_, line_number_)
|
||
|
{
|
||
|
}
|
||
|
};
|
||
|
|
||
|
namespace private_fsm
|
||
|
{
|
||
|
template <typename T = void>
|
||
|
class ifsm_state_helper
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
// Pass this whenever no state change is desired.
|
||
|
// The highest unsigned value of fsm_state_id_t.
|
||
|
static ETL_CONSTANT fsm_state_id_t No_State_Change = etl::integral_limits<fsm_state_id_t>::max;
|
||
|
|
||
|
// Pass this when this event also needs to be passed to the parent.
|
||
|
static ETL_CONSTANT fsm_state_id_t Pass_To_Parent = No_State_Change - 1U;
|
||
|
|
||
|
// Pass this when this event should trigger a self transition.
|
||
|
static ETL_CONSTANT fsm_state_id_t Self_Transition = No_State_Change - 2U;
|
||
|
};
|
||
|
|
||
|
template <typename T>
|
||
|
ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::No_State_Change;
|
||
|
|
||
|
template <typename T>
|
||
|
ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::Pass_To_Parent;
|
||
|
|
||
|
template <typename T>
|
||
|
ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::Self_Transition;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
/// Interface class for FSM states.
|
||
|
//***************************************************************************
|
||
|
class ifsm_state : public private_fsm::ifsm_state_helper<>
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
/// Allows ifsm_state functions to be private.
|
||
|
friend class etl::fsm;
|
||
|
friend class etl::hfsm;
|
||
|
|
||
|
using private_fsm::ifsm_state_helper<>::No_State_Change;
|
||
|
using private_fsm::ifsm_state_helper<>::Pass_To_Parent;
|
||
|
using private_fsm::ifsm_state_helper<>::Self_Transition;
|
||
|
|
||
|
#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
|
||
|
template <typename, typename, etl::fsm_state_id_t, typename...>
|
||
|
friend class fsm_state;
|
||
|
#else
|
||
|
template <typename, typename, etl::fsm_state_id_t,
|
||
|
typename, typename, typename, typename,
|
||
|
typename, typename, typename, typename,
|
||
|
typename, typename, typename, typename,
|
||
|
typename, typename, typename, typename>
|
||
|
friend class etl::fsm_state;
|
||
|
#endif
|
||
|
|
||
|
//*******************************************
|
||
|
/// Gets the id for this state.
|
||
|
//*******************************************
|
||
|
etl::fsm_state_id_t get_state_id() const
|
||
|
{
|
||
|
return state_id;
|
||
|
}
|
||
|
|
||
|
//*******************************************
|
||
|
/// Adds a child to this state.
|
||
|
/// Only of use when part of an HFSM.
|
||
|
//*******************************************
|
||
|
void add_child_state(etl::ifsm_state& state)
|
||
|
{
|
||
|
ETL_ASSERT(state.p_parent == ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
|
||
|
state.p_parent = this;
|
||
|
|
||
|
if (p_default_child == ETL_NULLPTR)
|
||
|
{
|
||
|
p_active_child = &state;
|
||
|
p_default_child = &state;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//*******************************************
|
||
|
/// Adds a list of child states.
|
||
|
/// Only of use when part of an HFSM.
|
||
|
//*******************************************
|
||
|
template <typename TSize>
|
||
|
void set_child_states(etl::ifsm_state** state_list, TSize size)
|
||
|
{
|
||
|
p_active_child = ETL_NULLPTR;
|
||
|
p_default_child = ETL_NULLPTR;
|
||
|
|
||
|
for (TSize i = 0; i < size; ++i)
|
||
|
{
|
||
|
ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
|
||
|
add_child_state(*state_list[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
//*******************************************
|
||
|
/// Constructor.
|
||
|
//*******************************************
|
||
|
ifsm_state(etl::fsm_state_id_t state_id_)
|
||
|
: state_id(state_id_),
|
||
|
p_context(ETL_NULLPTR),
|
||
|
p_parent(ETL_NULLPTR),
|
||
|
p_active_child(ETL_NULLPTR),
|
||
|
p_default_child(ETL_NULLPTR)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//*******************************************
|
||
|
/// Destructor.
|
||
|
//*******************************************
|
||
|
virtual ~ifsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//*******************************************
|
||
|
etl::fsm& get_fsm_context() const
|
||
|
{
|
||
|
return *p_context;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
virtual fsm_state_id_t process_event(const etl::imessage& message) = 0;
|
||
|
|
||
|
virtual fsm_state_id_t on_enter_state() { return No_State_Change; } // By default, do nothing.
|
||
|
virtual void on_exit_state() {} // By default, do nothing.
|
||
|
|
||
|
//*******************************************
|
||
|
void set_fsm_context(etl::fsm& context)
|
||
|
{
|
||
|
p_context = &context;
|
||
|
}
|
||
|
|
||
|
// The state id.
|
||
|
const etl::fsm_state_id_t state_id;
|
||
|
|
||
|
// A pointer to the FSM context.
|
||
|
etl::fsm* p_context;
|
||
|
|
||
|
// A pointer to the parent.
|
||
|
ifsm_state* p_parent;
|
||
|
|
||
|
// A pointer to the active child.
|
||
|
ifsm_state* p_active_child;
|
||
|
|
||
|
// A pointer to the default active child.
|
||
|
ifsm_state* p_default_child;
|
||
|
|
||
|
// Disabled.
|
||
|
ifsm_state(const ifsm_state&);
|
||
|
ifsm_state& operator =(const ifsm_state&);
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
/// The FSM class.
|
||
|
//***************************************************************************
|
||
|
class fsm : public etl::imessage_router
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
friend class etl::hfsm;
|
||
|
using imessage_router::receive;
|
||
|
|
||
|
//*******************************************
|
||
|
/// Constructor.
|
||
|
//*******************************************
|
||
|
fsm(etl::message_router_id_t id)
|
||
|
: imessage_router(id)
|
||
|
, p_state(ETL_NULLPTR)
|
||
|
, state_list(ETL_NULLPTR)
|
||
|
, number_of_states(0U)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//*******************************************
|
||
|
/// 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);
|
||
|
|
||
|
ETL_ASSERT(number_of_states > 0, ETL_ERROR(etl::fsm_state_list_exception));
|
||
|
ETL_ASSERT(number_of_states < ifsm_state::No_State_Change, ETL_ERROR(etl::fsm_state_list_exception));
|
||
|
|
||
|
for (etl::fsm_state_id_t i = 0; i < size; ++i)
|
||
|
{
|
||
|
ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
|
||
|
ETL_ASSERT(state_list[i]->get_state_id() == i, ETL_ERROR(etl::fsm_state_list_order_exception));
|
||
|
state_list[i]->set_fsm_context(*this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//*******************************************
|
||
|
/// Starts the FSM.
|
||
|
/// Can only be called once.
|
||
|
/// Subsequent calls will do nothing.
|
||
|
///\param call_on_enter_state If true will call on_enter_state() for the first state. Default = true.
|
||
|
//*******************************************
|
||
|
virtual void start(bool call_on_enter_state = true)
|
||
|
{
|
||
|
// Can only be started once.
|
||
|
if (p_state == ETL_NULLPTR)
|
||
|
{
|
||
|
p_state = state_list[0];
|
||
|
ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
|
||
|
|
||
|
if (call_on_enter_state)
|
||
|
{
|
||
|
etl::fsm_state_id_t next_state_id;
|
||
|
etl::ifsm_state* p_last_state;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
p_last_state = p_state;
|
||
|
next_state_id = p_state->on_enter_state();
|
||
|
if (next_state_id != ifsm_state::No_State_Change)
|
||
|
{
|
||
|
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||
|
p_state = state_list[next_state_id];
|
||
|
}
|
||
|
} while (p_last_state != p_state);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//*******************************************
|
||
|
/// Top level message handler for the FSM.
|
||
|
//*******************************************
|
||
|
void receive(const etl::imessage& message) ETL_OVERRIDE
|
||
|
{
|
||
|
if (is_started())
|
||
|
{
|
||
|
etl::fsm_state_id_t next_state_id = p_state->process_event(message);
|
||
|
|
||
|
if (have_changed_state(next_state_id))
|
||
|
{
|
||
|
ETL_ASSERT_OR_RETURN(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||
|
etl::ifsm_state* p_next_state = state_list[next_state_id];
|
||
|
|
||
|
do
|
||
|
{
|
||
|
p_state->on_exit_state();
|
||
|
p_state = p_next_state;
|
||
|
|
||
|
next_state_id = p_state->on_enter_state();
|
||
|
|
||
|
if (have_changed_state(next_state_id))
|
||
|
{
|
||
|
ETL_ASSERT_OR_RETURN(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||
|
p_next_state = state_list[next_state_id];
|
||
|
}
|
||
|
} while (p_next_state != p_state); // Have we changed state again?
|
||
|
}
|
||
|
else if (is_self_transition(next_state_id))
|
||
|
{
|
||
|
p_state->on_exit_state();
|
||
|
p_state->on_enter_state();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ETL_ASSERT_FAIL(ETL_ERROR(etl::fsm_not_started));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
using imessage_router::accepts;
|
||
|
|
||
|
//*******************************************
|
||
|
/// Does this FSM accept the message id?
|
||
|
/// Yes, it accepts everything!
|
||
|
//*******************************************
|
||
|
bool accepts(etl::message_id_t) const ETL_OVERRIDE
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//*******************************************
|
||
|
/// Gets the current state id.
|
||
|
//*******************************************
|
||
|
etl::fsm_state_id_t get_state_id() const
|
||
|
{
|
||
|
ETL_ASSERT(p_state != ETL_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 != ETL_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 != ETL_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 != ETL_NULLPTR;
|
||
|
}
|
||
|
|
||
|
//*******************************************
|
||
|
/// Reset the FSM to pre-started state.
|
||
|
///\param call_on_exit_state If true will call on_exit_state() for the current state. Default = false.
|
||
|
//*******************************************
|
||
|
virtual void reset(bool call_on_exit_state = false)
|
||
|
{
|
||
|
if ((p_state != ETL_NULLPTR) && call_on_exit_state)
|
||
|
{
|
||
|
p_state->on_exit_state();
|
||
|
}
|
||
|
|
||
|
p_state = ETL_NULLPTR;
|
||
|
}
|
||
|
|
||
|
//********************************************
|
||
|
ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//********************************************
|
||
|
bool is_producer() const ETL_OVERRIDE
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//********************************************
|
||
|
bool is_consumer() const ETL_OVERRIDE
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
//********************************************
|
||
|
bool have_changed_state(etl::fsm_state_id_t next_state_id) const
|
||
|
{
|
||
|
return (next_state_id != p_state->get_state_id()) &&
|
||
|
(next_state_id != ifsm_state::No_State_Change) &&
|
||
|
(next_state_id != ifsm_state::Self_Transition);
|
||
|
}
|
||
|
|
||
|
//********************************************
|
||
|
bool is_self_transition(etl::fsm_state_id_t next_state_id) const
|
||
|
{
|
||
|
return (next_state_id == ifsm_state::Self_Transition);
|
||
|
}
|
||
|
|
||
|
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.
|
||
|
};
|
||
|
|
||
|
//*************************************************************************************************
|
||
|
// For C++17 and above.
|
||
|
//*************************************************************************************************
|
||
|
#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
|
||
|
//***************************************************************************
|
||
|
// The definition for all types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||
|
class fsm_state : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
//********************************************
|
||
|
struct result_t
|
||
|
{
|
||
|
bool was_handled;
|
||
|
etl::fsm_state_id_t state_id;
|
||
|
};
|
||
|
|
||
|
//********************************************
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
|
||
|
const bool was_handled = (process_event_type<TMessageTypes>(message, new_state_id) || ...);
|
||
|
|
||
|
if (!was_handled || (new_state_id == Pass_To_Parent))
|
||
|
{
|
||
|
new_state_id = (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
|
||
|
}
|
||
|
|
||
|
return new_state_id;
|
||
|
}
|
||
|
|
||
|
//********************************************
|
||
|
template <typename TMessage>
|
||
|
bool process_event_type(const etl::imessage& msg, etl::fsm_state_id_t& new_state_id)
|
||
|
{
|
||
|
if (TMessage::ID == msg.get_message_id())
|
||
|
{
|
||
|
new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const TMessage&>(msg));
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/// Definition of STATE_ID
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||
|
ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::STATE_ID;
|
||
|
|
||
|
#else
|
||
|
//*************************************************************************************************
|
||
|
// For C++14 and below.
|
||
|
//*************************************************************************************************
|
||
|
//***************************************************************************
|
||
|
// The definition for all 16 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
typename T1 = void, 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 fsm_state : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
|
||
|
case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
|
||
|
case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
|
||
|
case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
|
||
|
case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
|
||
|
case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
|
||
|
case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
|
||
|
case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
|
||
|
case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
|
||
|
case T13::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T13&>(message)); break;
|
||
|
case T14::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T14&>(message)); break;
|
||
|
case T15::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T15&>(message)); break;
|
||
|
case T16::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T16&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 15 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
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 fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
|
||
|
case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
|
||
|
case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
|
||
|
case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
|
||
|
case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
|
||
|
case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
|
||
|
case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
|
||
|
case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
|
||
|
case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
|
||
|
case T13::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T13&>(message)); break;
|
||
|
case T14::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T14&>(message)); break;
|
||
|
case T15::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T15&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 14 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
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 fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
|
||
|
case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
|
||
|
case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
|
||
|
case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
|
||
|
case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
|
||
|
case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
|
||
|
case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
|
||
|
case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
|
||
|
case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
|
||
|
case T13::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T13&>(message)); break;
|
||
|
case T14::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T14&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 13 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
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 fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
|
||
|
case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
|
||
|
case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
|
||
|
case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
|
||
|
case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
|
||
|
case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
|
||
|
case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
|
||
|
case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
|
||
|
case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
|
||
|
case T13::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T13&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 12 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
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 fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, void, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
|
||
|
case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
|
||
|
case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
|
||
|
case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
|
||
|
case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
|
||
|
case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
|
||
|
case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
|
||
|
case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
|
||
|
case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 11 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
typename T1, typename T2, typename T3, typename T4,
|
||
|
typename T5, typename T6, typename T7, typename T8,
|
||
|
typename T9, typename T10, typename T11>
|
||
|
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, void, void, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
|
||
|
case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
|
||
|
case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
|
||
|
case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
|
||
|
case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
|
||
|
case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
|
||
|
case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
|
||
|
case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 10 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
typename T1, typename T2, typename T3, typename T4,
|
||
|
typename T5, typename T6, typename T7, typename T8,
|
||
|
typename T9, typename T10>
|
||
|
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, void, void, void, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
|
||
|
case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
|
||
|
case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
|
||
|
case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
|
||
|
case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
|
||
|
case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
|
||
|
case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 9 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
typename T1, typename T2, typename T3, typename T4,
|
||
|
typename T5, typename T6, typename T7, typename T8,
|
||
|
typename T9>
|
||
|
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, void, void, void, void, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
|
||
|
case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
|
||
|
case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
|
||
|
case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
|
||
|
case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
|
||
|
case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 8 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
typename T1, typename T2, typename T3, typename T4,
|
||
|
typename T5, typename T6, typename T7, typename T8>
|
||
|
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, void, void, void, void, void, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
|
||
|
case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
|
||
|
case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
|
||
|
case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
|
||
|
case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 7 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
typename T1, typename T2, typename T3, typename T4,
|
||
|
typename T5, typename T6, typename T7>
|
||
|
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
|
||
|
case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
|
||
|
case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
|
||
|
case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 6 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
typename T1, typename T2, typename T3, typename T4,
|
||
|
typename T5, typename T6>
|
||
|
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
|
||
|
case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
|
||
|
case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 5 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
typename T1, typename T2, typename T3, typename T4,
|
||
|
typename T5>
|
||
|
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
|
||
|
case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 4 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
typename T1, typename T2, typename T3, typename T4>
|
||
|
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 3 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
typename T1, typename T2, typename T3>
|
||
|
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 2 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
typename T1, typename T2>
|
||
|
class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, void, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 1 message type.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
typename T1>
|
||
|
class fsm_state<TContext, TDerived, STATE_ID_, T1, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
etl::fsm_state_id_t new_state_id;
|
||
|
etl::message_id_t event_id = message.get_message_id();
|
||
|
|
||
|
switch (event_id)
|
||
|
{
|
||
|
case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
|
||
|
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
|
||
|
}
|
||
|
|
||
|
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//***************************************************************************
|
||
|
// Specialisation for 0 message types.
|
||
|
//***************************************************************************
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_>
|
||
|
class fsm_state<TContext, TDerived, STATE_ID_, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||
|
|
||
|
fsm_state()
|
||
|
: ifsm_state(STATE_ID)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
~fsm_state()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TContext& get_fsm_context() const
|
||
|
{
|
||
|
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||
|
}
|
||
|
private:
|
||
|
|
||
|
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||
|
{
|
||
|
return p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
|
||
|
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, typename T16>
|
||
|
ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::STATE_ID;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#include "private/minmax_pop.h"
|
||
|
|
||
|
#endif
|