Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

259 lines
8.7 KiB

//-----------------------------------------------------------------------------
//
//
// File: statemachinebase.cpp
//
// Description:
// Implementation of CStateMachineBaseClass
//
// Author: Mike Swafford (MikeSwa)
//
// History:
// 12/11/2000 - MikeSwa Created
//
// Copyright (C) 2000 Microsoft Corporation
//
//-----------------------------------------------------------------------------
#include "aqprecmp.h"
#include "statemachinebase.h"
//---[ CStateMachineBase::CStateMachineBase ]-----------------------
//
//
// Description:
// CStateMachineBase constructor
// Parameters:
// - dwInitialState Initial state to set state
// machine to
// dwStateMachineSignature Signature of the state machine
// subclass
// Returns:
// -
// History:
// 6/5/2000 - t-toddc Created
//
//------------------------------------------------------------------
CStateMachineBase::CStateMachineBase(DWORD dwInitialState,
DWORD dwStateMachineSignature) :
m_dwSignature(STATE_MACHINE_BASE_SIG),
m_dwStateMachineSignature(dwStateMachineSignature),
m_dwCurrentState(dwInitialState)
{
};
//---[ CStateMachineBase::dwGetCurrentState ]----------------------
//
//
// Description:
// returns the current state of the state machine
// Parameters:
// -
// Returns:
// - current state
// History:
// 6/5/2000 - t-toddc Created
//
//------------------------------------------------------------------
DWORD CStateMachineBase::dwGetCurrentState()
{
return m_dwCurrentState;
}
//---[ CStateMachineBase::dwGetNextState ]-------------------------
//
//
// Description:
// sets the next state based on current state and input action.
// Uses InterlockedCompareExchange to make sure that the state
// transition is thread-safe.
// Parameters:
// - dwAction the current action causing the state transition
// Returns:
// - the resultant state based on the current state and
// input action
// History:
// 6/5/2000 - t-toddc Created
//
//------------------------------------------------------------------
DWORD CStateMachineBase::dwGetNextState(DWORD dwAction)
{
TraceFunctEnter("CStateMachineBase::dwGetNextState");
DWORD dwCurrentState;
DWORD dwNextState;
do
{
dwCurrentState = m_dwCurrentState;
dwNextState = dwCalcStateFromStateAndAction(dwCurrentState, dwAction);
if (dwCurrentState == dwNextState)
break; // no work to be done
} while (InterlockedCompareExchange((LPLONG) &m_dwCurrentState,
(LONG) dwNextState,
(LONG) dwCurrentState)!= (LONG) dwCurrentState);
DebugTrace((LPARAM) this,
"CStateMachineBase state transition: %X->%X",
dwCurrentState,
dwNextState);
TraceFunctLeave();
return dwNextState;
}
//---[ CStateMachineBase::dwCalcStateFromStateAndAction ]------------
//
//
// Description:
// iterates through the state transition table to find the
// next state associated with the current state and input action
// Parameters:
// - dwStartState start state for this transition
// dwAction the action associated with this transition
// Returns:
// - the resultant state associated with current state and action
// History:
// 6/5/2000 - t-toddc Created
//
//
//------------------------------------------------------------------
DWORD CStateMachineBase::dwCalcStateFromStateAndAction(DWORD dwStartState, DWORD dwAction)
{
TraceFunctEnter("CStateMachineBase::dwCalcStateFromStateAndAction");
// if the action is unknown to state table, return start state
DWORD dwNextState = dwStartState;
DWORD i;
const STATE_TRANSITION* pTransitionTable;
DWORD dwNumTransitions;
BOOL fFoundTransition = FALSE;
// obtain the transition table
getTransitionTable(&pTransitionTable, &dwNumTransitions);
// find the new state
for(i=0; i < dwNumTransitions; i++)
{
if (pTransitionTable[i].dwCurrentState == dwStartState &&
pTransitionTable[i].dwAction == dwAction)
{
dwNextState = pTransitionTable[i].dwNextState;
fFoundTransition = TRUE;
break;
}
}
ASSERT(fFoundTransition && "action unknown to state table");
if (!fFoundTransition)
DebugTrace((LPARAM) this,"action %X unknown to state tabe", dwAction);
TraceFunctLeave();
return dwNextState;
}
//---[ CStateMachineBase::fValidateStateTable ]---------------------
//
//
// Description:
// loops through all transitions and checks that
// a) all possible states are start states
// b) for every state, every possible action yields another state
// Parameters:
// -
// Returns:
// - true/false if state table is valid/invalid
// History:
// 6/5/2000 - t-toddc Created
//
//------------------------------------------------------------------
BOOL CStateMachineBase::fValidateStateTable()
{
TraceFunctEnter("CStateMachineBase::fValidateStateTable");
DWORD i, j, k; // iterators
DWORD dwEndState;
DWORD dwAction;
DWORD dwCurrentState;
BOOL fFoundEndStateAsStartState = false;
BOOL fActionSupportedByEveryState = false;
const STATE_TRANSITION* pTransitionTable;
DWORD dwNumTransitions;
BOOL fRetVal = false;
// obtain the transition table
getTransitionTable(&pTransitionTable, &dwNumTransitions);
for(i = 0; i < dwNumTransitions; i++)
{
// initialize booleans within loop
fFoundEndStateAsStartState = false;
// grab the current action
dwAction = pTransitionTable[i].dwAction;
// grab the current end state
dwEndState = pTransitionTable[i].dwNextState;
// loop over all transitions
for (j = 0; j < dwNumTransitions; j++)
{
// check that the current end state is a start state
if (pTransitionTable[j].dwCurrentState == dwEndState)
{
fFoundEndStateAsStartState = true;
}
// check that every action is supported by every state
fActionSupportedByEveryState = false;
dwCurrentState = pTransitionTable[j].dwCurrentState;
// the current action might not be in this particular transition,
// but it must be in a transition with this dwCurrentState as the start state
if (pTransitionTable[j].dwAction != dwAction)
{
// loop over all transitions again to guarantee the above.
for(k = 0; k < dwNumTransitions; k++)
{
// there must exist a state transition with the current state
// from above and the given action
if (pTransitionTable[k].dwAction == dwAction &&
pTransitionTable[k].dwCurrentState == dwCurrentState)
{
fActionSupportedByEveryState = true;
break;
}
}
}
else
{
fActionSupportedByEveryState = true;
}
// bail on false if the current action is not supported by every state
ASSERT(fActionSupportedByEveryState &&
"Invalid state table: action not supported by every state");
if (!fActionSupportedByEveryState)
{
fRetVal = false;
DebugTrace((LPARAM) this,
"Invalid state table: action not supported by every state");
goto Cleanup;
}
// break out of inner loop if the current end state has been found
// as a start state
if (fFoundEndStateAsStartState)
break;
}
// bail on false if an end state is not also a start state
ASSERT(fFoundEndStateAsStartState &&
"Invalid state table: an end state is not also a start state");
if (!fFoundEndStateAsStartState)
{
fRetVal = false;
DebugTrace((LPARAM) this,
"Invalid state table: an end state is not also a start state");
goto Cleanup;
}
}
// if it makes it this far, it is undoubtedly valid.
fRetVal = true;
Cleanup:
TraceFunctLeave();
return fRetVal;
}