1
0
forked from 0ad/0ad

Constrain the FSM-transition to have at most one action.

Accepted By: @vladislavbelov
Differential Revision: https://code.wildfiregames.com/D5059
This was SVN commit r27768.
This commit is contained in:
phosit 2023-07-19 12:23:53 +00:00
parent 1ff0b8f69f
commit 8b761fec29
2 changed files with 24 additions and 78 deletions

View File

@ -35,26 +35,10 @@ void CFsmEvent::SetParamRef(void* pParam)
m_Param = pParam; m_Param = pParam;
} }
CFsmTransition::CFsmTransition(unsigned int state) CFsmTransition::CFsmTransition(const unsigned int state, const CallbackFunction action)
{ : m_CurrState{state},
m_CurrState = state; m_Action{action}
} {}
CFsmTransition::~CFsmTransition()
{
m_Actions.clear();
}
void CFsmTransition::RegisterAction(void* pAction, void* pContext)
{
CallbackFunction callback;
// Add action at the end of actions list
callback.pFunction = pAction;
callback.pContext = pContext;
m_Actions.push_back(callback);
}
void CFsmTransition::SetEvent(CFsmEvent* pEvent) void CFsmTransition::SetEvent(CFsmEvent* pEvent)
{ {
@ -66,22 +50,10 @@ void CFsmTransition::SetNextState(unsigned int nextState)
m_NextState = nextState; m_NextState = nextState;
} }
bool CFsmTransition::RunActions() const bool CFsmTransition::RunAction() const
{ {
bool result = true; return !m_Action.pFunction ||
reinterpret_cast<Action*>(m_Action.pFunction)(m_Action.pContext, m_Event);
CallbackList::const_iterator it = m_Actions.begin();
for (; it != m_Actions.end(); ++it)
{
if (it->pFunction)
{
// Run action
Action* action = reinterpret_cast<Action*>(it->pFunction);
result &= action(it->pContext, m_Event);
}
}
return result;
} }
CFsm::CFsm() CFsm::CFsm()
@ -150,7 +122,8 @@ CFsmEvent* CFsm::AddEvent(unsigned int eventType)
return pEvent; return pEvent;
} }
CFsmTransition* CFsm::AddTransition(unsigned int state, unsigned int eventType, unsigned int nextState ) CFsmTransition* CFsm::AddTransition(unsigned int state, unsigned int eventType, unsigned int nextState,
void* pAction /* = nullptr */, void* pContext /* = nullptr*/)
{ {
// Make sure we store the current state // Make sure we store the current state
AddState(state); AddState(state);
@ -164,7 +137,7 @@ CFsmTransition* CFsm::AddTransition(unsigned int state, unsigned int eventType,
return nullptr; return nullptr;
// Create new transition // Create new transition
CFsmTransition* pNewTransition = new CFsmTransition(state); CFsmTransition* pNewTransition = new CFsmTransition(state, {pAction, pContext});
// Setup new transition // Setup new transition
pNewTransition->SetEvent(pEvent); pNewTransition->SetEvent(pEvent);
@ -176,20 +149,6 @@ CFsmTransition* CFsm::AddTransition(unsigned int state, unsigned int eventType,
return pNewTransition; return pNewTransition;
} }
CFsmTransition* CFsm::AddTransition(unsigned int state, unsigned int eventType, unsigned int nextState,
void* pAction, void* pContext)
{
CFsmTransition* pTransition = AddTransition(state, eventType, nextState);
if (!pTransition)
return nullptr;
// If action specified, register it
if (pAction)
pTransition->RegisterAction(pAction, pContext);
return pTransition;
}
CFsmTransition* CFsm::GetTransition(unsigned int state, unsigned int eventType) const CFsmTransition* CFsm::GetTransition(unsigned int state, unsigned int eventType) const
{ {
if (!IsValidState(state)) if (!IsValidState(state))
@ -259,7 +218,7 @@ bool CFsm::Update(unsigned int eventType, void* pEventParam)
// to override this) // to override this)
SetNextState(pTransition->GetNextState()); SetNextState(pTransition->GetNextState());
if (!pTransition->RunActions()) if (!pTransition->RunAction())
return false; return false;
SetCurrState(GetNextState()); SetCurrState(GetNextState());

View File

@ -34,14 +34,13 @@ using Action = bool(void* pContext, const CFsmEvent* pEvent);
struct CallbackFunction struct CallbackFunction
{ {
void* pFunction; void* pFunction{nullptr};
void* pContext; void* pContext{nullptr};
}; };
using StateSet = std::set<unsigned int>; using StateSet = std::set<unsigned int>;
using EventMap = std::map<unsigned int, CFsmEvent*>; using EventMap = std::map<unsigned int, CFsmEvent*>;
using TransitionList = std::vector<CFsmTransition*>; using TransitionList = std::vector<CFsmTransition*>;
using CallbackList = std::vector<CallbackFunction>;
/** /**
* Represents a signal in the state machine that a change has occurred. * Represents a signal in the state machine that a change has occurred.
@ -81,16 +80,10 @@ class CFsmTransition
{ {
NONCOPYABLE(CFsmTransition); NONCOPYABLE(CFsmTransition);
public: public:
CFsmTransition(unsigned int state);
~CFsmTransition();
/** /**
* Registers an action that will be executed when the transition occurs. * @param action Object executed upon transition.
* @param pAction the function which will be executed.
* @param pContext data passed to the function.
*/ */
void RegisterAction(void* pAction, void* pContext); CFsmTransition(const unsigned int state, const CallbackFunction action);
/** /**
* Set event for which transition will occur. * Set event for which transition will occur.
@ -115,23 +108,23 @@ public:
return m_CurrState; return m_CurrState;
} }
const CallbackList& GetActions() const CallbackFunction GetAction() const
{ {
return m_Actions; return m_Action;
} }
/** /**
* Executes actions for the transition. * Executes action for the transition.
* @note If there are no actions, assume true. * @note If there are no action, assume true.
* @return whether all the actions returned true. * @return whether the action returned true.
*/ */
bool RunActions() const; bool RunAction() const;
private: private:
unsigned int m_CurrState; unsigned int m_CurrState;
unsigned int m_NextState; unsigned int m_NextState;
CFsmEvent* m_Event; CFsmEvent* m_Event;
CallbackList m_Actions; CallbackFunction m_Action;
}; };
/** /**
@ -160,7 +153,7 @@ public:
virtual void Setup(); virtual void Setup();
/** /**
* Clear event, action lists and reset state machine. * Clear event, transition lists and reset state machine.
*/ */
void Shutdown(); void Shutdown();
@ -181,14 +174,8 @@ public:
* Adds a new transistion to the state machine. * Adds a new transistion to the state machine.
* @return a pointer to the new transition. * @return a pointer to the new transition.
*/ */
CFsmTransition* AddTransition(unsigned int state, unsigned int eventType, unsigned int nextState );
/**
* Adds a new transition to the state machine.
* @return a pointer to the new transition.
*/
CFsmTransition* AddTransition(unsigned int state, unsigned int eventType, unsigned int nextState, CFsmTransition* AddTransition(unsigned int state, unsigned int eventType, unsigned int nextState,
void* pAction, void* pContext); void* pAction = nullptr, void* pContext = nullptr);
/** /**
* Looks up the transition given the state, event and next state to transition to. * Looks up the transition given the state, event and next state to transition to.