Changeset View
Changeset View
Standalone View
Standalone View
source/network/Fsm.h
- This file was added.
/* Copyright (C) 2017 Wildfire Games. | |||||
* This file is part of 0 A.D. | |||||
* | |||||
* 0 A.D. is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 2 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* 0 A.D. is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef FSM_H | |||||
#define FSM_H | |||||
#include "NetMessageBuffer.h" | |||||
class CFsmEvent; | |||||
class CFsmTransition; | |||||
class CFsm; | |||||
using Action = bool(*)(void* pContext, const CFsmEvent& pEvent); | |||||
struct StoredAction | |||||
{ | |||||
Action m_Function; | |||||
void* m_Context; | |||||
}; | |||||
/** | |||||
* Represents a signal in the state machine that a change has occurred. | |||||
* The CFsmEvent objects are under the control of CFsm so | |||||
* they are created and deleted via CFsm. | |||||
*/ | |||||
class CFsmEvent | |||||
{ | |||||
public: | |||||
CFsmEvent(u32 type, const CNetMessageBuffer* buffer); | |||||
u32 GetType() const | |||||
leper: Why not `NetMessageType`? | |||||
{ | |||||
return m_Type; | |||||
} | |||||
const CNetMessageBuffer& GetMessageBuffer() const | |||||
{ | |||||
ENSURE(m_Buffer); | |||||
return *m_Buffer; | |||||
} | |||||
private: | |||||
const CNetMessageBuffer* m_Buffer; | |||||
u32 m_Type; | |||||
}; | |||||
/** | |||||
* An association of event, condition, action and next state. | |||||
*/ | |||||
class CFsmTransition | |||||
{ | |||||
public: | |||||
CFsmTransition(u32 state, u32 eventType, u32 nextState, StoredAction action); | |||||
u32 GetCurrState() const | |||||
{ | |||||
return m_CurrState; | |||||
} | |||||
u32 GetEventType() const | |||||
{ | |||||
return m_EventType; | |||||
} | |||||
u32 GetNextState() const | |||||
{ | |||||
return m_NextState; | |||||
} | |||||
bool RunAction(const CFsmEvent* event) const; | |||||
private: | |||||
u32 m_CurrState; | |||||
u32 m_EventType; | |||||
u32 m_NextState; | |||||
StoredAction m_Action; | |||||
Not Done Inline ActionsIs anything actually inheriting from this? leper: Is anything actually inheriting from this? | |||||
}; | |||||
/** | |||||
* Manages states, events, actions and transitions | |||||
* between states. It provides an interface for advertising | |||||
* events and track the current state. The implementation is | |||||
* a Mealy state machine, so the system respond to events | |||||
* and execute some action. | |||||
* | |||||
* A Mealy state machine has behaviour associated with state | |||||
* transitions; Mealy machines are event driven where an | |||||
* event triggers a state transition | |||||
*/ | |||||
class CFsm | |||||
{ | |||||
public: | |||||
CFsm(u32 firstState); | |||||
virtual ~CFsm() {} | |||||
void AddTransition(u32 state, u32 eventType, u32 nextState); | |||||
leperUnsubmitted Not Done Inline ActionsWhy aren't we using NetMessageType for eventType? (Applies to the whole class + users; mostly this would remove all the (uint) casts for AddTransition callers.) leper: Why aren't we using `NetMessageType` for eventType? (Applies to the whole class + users; mostly… | |||||
void AddTransition(u32 state, u32 eventType, u32 nextState, Action action, void* context); | |||||
void SetCurrState(u32 state) | |||||
{ | |||||
m_CurrState = state; | |||||
} | |||||
u32 GetCurrState() const | |||||
{ | |||||
return m_CurrState; | |||||
} | |||||
void SetNextState(u32 nextState) | |||||
{ | |||||
m_NextState = nextState; | |||||
} | |||||
bool Update(u32 type, const CNetMessageBuffer* message); | |||||
private: | |||||
const u32 INVALID_STATE = ~0; | |||||
using StateSet = std::set<u32>; | |||||
using EventSet = std::set<u32>; | |||||
using TransitionList = std::vector<CFsmTransition>; | |||||
const CFsmTransition* GetTransition(u32 state, u32 eventType) const; | |||||
void AddState(u32 state) | |||||
{ | |||||
m_States.insert(state); | |||||
} | |||||
void AddEvent(u32 eventType) | |||||
{ | |||||
m_Events.insert(eventType); | |||||
} | |||||
bool IsValidState(u32 state) const | |||||
{ | |||||
return m_States.find(state) != m_States.end(); | |||||
} | |||||
bool IsValidEvent(u32 eventType) const | |||||
{ | |||||
return m_Events.find(eventType) != m_Events.end(); | |||||
} | |||||
u32 m_FirstState; | |||||
u32 m_CurrState; | |||||
u32 m_NextState; | |||||
StateSet m_States; | |||||
EventSet m_Events; | |||||
TransitionList m_Transitions; | |||||
}; | |||||
#endif // FSM_H |
Wildfire Games · Phabricator
Why not NetMessageType?