Make AIRegisteredStateMachines more robust.
Now that a call to cont() can schedule a run of the statemachine, we need this change to make it robust (the comment that cont() does never access mRegisteredStateMachines no longer holds).
This commit is contained in:
@@ -36,26 +36,52 @@
|
|||||||
// Additional information stored per registered statemachine in AIRegisteredStateMachines std::map.
|
// Additional information stored per registered statemachine in AIRegisteredStateMachines std::map.
|
||||||
struct AIRSData {
|
struct AIRSData {
|
||||||
bool mOneShot;
|
bool mOneShot;
|
||||||
AIRSData(void) { }
|
bool mRunning;
|
||||||
AIRSData(bool one_shot) : mOneShot(one_shot) { }
|
AIRSData(void) : mRunning(false) { }
|
||||||
|
AIRSData(bool one_shot) : mOneShot(one_shot), mRunning(false) { }
|
||||||
|
void operator=(bool one_shot) { mOneShot = one_shot; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// A list of all statemachines registered for a particular event, and an API to work on it.
|
// A list of all statemachines registered for a particular event, and an API to work on it.
|
||||||
struct AIRegisteredStateMachines {
|
struct AIRegisteredStateMachines {
|
||||||
typedef std::map<AIStateMachine*, AIRSData> rsm_type;
|
typedef std::map<AIStateMachine*, AIRSData> rsm_type;
|
||||||
rsm_type mRegisteredStateMachines;
|
rsm_type mRegisteredStateMachines;
|
||||||
void Register(AIStateMachine* statemachine, bool one_shot) { mRegisteredStateMachines[statemachine] = one_shot; }
|
void Register(AIStateMachine* statemachine, bool one_shot);
|
||||||
void Unregister(AIStateMachine* statemachine) { mRegisteredStateMachines.erase(statemachine); }
|
void Unregister(AIStateMachine* statemachine);
|
||||||
void trigger(void);
|
void trigger(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inline this, because it's only called from one place.
|
// Inline these, because they are only called from one place.
|
||||||
|
|
||||||
|
inline void AIRegisteredStateMachines::Register(AIStateMachine* statemachine, bool one_shot)
|
||||||
|
{
|
||||||
|
mRegisteredStateMachines[statemachine] = one_shot;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void AIRegisteredStateMachines::Unregister(AIStateMachine* statemachine)
|
||||||
|
{
|
||||||
|
rsm_type::iterator sm = mRegisteredStateMachines.find(statemachine);
|
||||||
|
if (sm != mRegisteredStateMachines.end())
|
||||||
|
{
|
||||||
|
if (!sm->second.mRunning)
|
||||||
|
{
|
||||||
|
mRegisteredStateMachines.erase(sm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sm->second.mOneShot = true; // Delay the erase till we return to trigger().
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void AIRegisteredStateMachines::trigger(void)
|
inline void AIRegisteredStateMachines::trigger(void)
|
||||||
{
|
{
|
||||||
rsm_type::iterator sm = mRegisteredStateMachines.begin();
|
rsm_type::iterator sm = mRegisteredStateMachines.begin();
|
||||||
while(sm != mRegisteredStateMachines.end())
|
while(sm != mRegisteredStateMachines.end())
|
||||||
{
|
{
|
||||||
sm->first->cont(); // This is safe, cont() does never access mRegisteredStateMachines.
|
sm->second.mRunning = true;
|
||||||
|
sm->first->cont(); // This is safe, cont() doesn't invalidates sm while mRunning is set.
|
||||||
|
sm->second.mRunning = false;
|
||||||
if (sm->second.mOneShot)
|
if (sm->second.mOneShot)
|
||||||
mRegisteredStateMachines.erase(sm++);
|
mRegisteredStateMachines.erase(sm++);
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user